]> git.andy128k.dev Git - ipf.git/commitdiff
New File/Image Manager
authoravl <alex.litovchenko@gmail.com>
Wed, 24 Dec 2008 14:10:19 +0000 (16:10 +0200)
committeravl <alex.litovchenko@gmail.com>
Wed, 24 Dec 2008 14:10:19 +0000 (16:10 +0200)
384 files changed:
ipf/admin/media/tiny_mce/plugins/kfm/.htaccess [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/api/api.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/api/cms_hooks.php.dist [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/api/config.php.dist [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/configuration.dist.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/configuration.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/docs/license.txt [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/docs/readme.txt [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/docs/version.txt [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/fckplugin.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/get.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/i/bg-black-75.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/db.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/db.sqlite.pdo.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/directories.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/directory.class.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/file.class.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/files.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/image.class.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/images.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/json.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/kaejax.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/kfm.class.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/lang.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/login.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/object.class.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/JSON.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Date.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Datatype/Common.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Datatype/mysql.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Datatype/pgsql.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Datatype/sqlite.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Function/Common.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Function/mysql.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Function/pgsql.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Function/sqlite.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Manager/Common.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Manager/mysql.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Manager/pgsql.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Manager/sqlite.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Native/Common.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Native/mysql.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Native/pgsql.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Native/sqlite.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Reverse/Common.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Reverse/mysql.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Reverse/pgsql.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Reverse/sqlite.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/mysql.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/pgsql.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/sqlite.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Extended.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Iterator.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/LOB.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/OS/Guess.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/PEAR.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/System.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/includes/session.class.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/index.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/initialise.php [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/j/alerts.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/all.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/browser-specific.ie.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/browser-specific.konqueror.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/common.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/contextmenu.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/directories.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/file.class.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/file.selections.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/file.text-editing.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/files.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/hooks.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/images.and.icons.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/all.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery-1.2.2.pack.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.dimensions.pack.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.grid.columnSizing.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.idrag.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.impromptu.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.iutil.pack.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.tablesorter.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.tablesorter.pack.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/kaejax_replaces.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/kdnd.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/kfm.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/modal.dialog.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/j/mootools.v1.11/.htaccess [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/mootools.v1.11/mootools.v1.11.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/notice.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/panels.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/resize_handler.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/search.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/swfupload-2.1.0b2/swfupload.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/j/swfupload-2.1.0b2/swfupload.swfobject.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/j/swfupload-2.1.0b2/swfupload_f8.swf [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/j/swfupload-2.1.0b2/swfupload_f9.swf [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/j/tags.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/j/variables.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/bg.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/bg.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/cz.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/cz.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/da.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/da.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/de.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/de.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/en.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/en.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/es.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/lang/es.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/fa.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/fa.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/fi.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/fi.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/fr.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/fr.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/ga.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/ga.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/hu.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/hu.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/it.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/it.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/nl.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/nl.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/pl.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/pl.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/ro.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/lang/ro.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/ru.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/lang/ru.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/sv.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/lang/sv.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/maintenance.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/codepress.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/codepress.html [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/codepress.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/engines/gecko.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/engines/khtml.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/engines/msie.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/engines/older.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/engines/opera.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/images/line-numbers.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/index.html [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/asp.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/asp.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/autoit.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/autoit.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/csharp.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/csharp.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/css.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/css.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/generic.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/generic.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/html.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/html.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/java.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/java.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/javascript.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/javascript.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/perl.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/perl.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/php.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/php.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/ruby.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/ruby.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/sql.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/sql.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/text.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/text.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/vbscript.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/vbscript.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/xsl.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/xsl.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/license.txt [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/edit.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/plugin.css [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/plugin.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/copy_to_clipboard/_clipboard.swf [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/copy_to_clipboard/plugin.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/croparea.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/cropper.css [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/cropper.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/img/crop.gif [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/builder.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/controls.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/dragdrop.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/effects.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/prototype.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/scriptaculous.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/slider.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/unittest.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/licence.txt [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/marqueeHoriz.gif [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/marqueeVert.gif [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/plugin.css [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/plugin.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/extract_zip/extract_zip.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/extract_zip/plugin.css [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/extract_zip/plugin.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/file_details/file_details.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/file_details/plugin.css [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/file_details/plugin.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_resize_multiple/plugin.css [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_resize_multiple/plugin.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_resize_multiple/resize_image.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_rotate/plugin.css [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_rotate/plugin.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_rotate/rotate_ccw.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_rotate/rotate_cw.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer.zip [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/jwplayer.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/mediaplayer.swf [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/playlist.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/plugin.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/swfobject.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/lightbox/plugin.css [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/lightbox/plugin.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/lightbox/slideshow_icon.jpg [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/plugins/return_thumbnail/plugin.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.mysql.create.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.mysql.update.0.7.1.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.mysql.update.0.7.2.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.mysql.update.0.9.1.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.mysql.update.0.9.2.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.pgsql.create.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.pgsql.update.0.7.1.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.pgsql.update.0.7.2.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.pgsql.update.0.9.1.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.pgsql.update.0.9.2.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.sqlite.create.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.sqlite.update.0.7.1.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.sqlite.update.0.7.2.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.sqlite.update.0.9.1.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.sqlite.update.0.9.2.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/image_resize/plugin.css [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/image_resize/plugin.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/image_resize/resize_image.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.0.7.1.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.0.7.2.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.0.8.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.0.9.1.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.0.9.2.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.1.0.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.1.1.1.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.1.1.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.1.2.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.1.3.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/.htaccess [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/bitsandpieces/panelheader-bg.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/bitsandpieces/panelheader.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/css.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/folders.gif [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/hooks.css [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/actions/1rightarrow.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/aac.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/aac2.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ape.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/avi.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/avi2.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/bz2.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/chm.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/core.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/deb.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/doc.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/document.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/empty.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/flac.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/folder_setting.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/font.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/font_truetype.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/gz.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/html.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/mov.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/mp3.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/mp4.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/odt.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ogg.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/pdf.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/php.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ppt.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/qt.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ram.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rar.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rm.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rmvb.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rpm.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rt.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rtf.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ruby.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rv.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/svg.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/sxw.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/tar.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/tgz.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/txt.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/txt2.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/unknown.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/xls.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/zip.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/loader.gif [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/aac.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/aac2.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ape.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/avi.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/avi2.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/bz2.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/chm.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/core.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/deb.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/doc.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/document.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/empty.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/flac.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/folder_setting.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/font.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/font_truetype.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/gz.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/html.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/mov.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/mp3.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/mp4.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/odt.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ogg.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/pdf.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/php.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/qt.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ram.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rar.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rm.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rmvb.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rpm.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rt.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rtf.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ruby.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rv.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/svg.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/sxw.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/tar.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/tgz.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/txt.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/txt2.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/unknown.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/xls.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/zip.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/add_tags.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/ark_selectall.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/downloadicon.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/edit.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/extract_zip.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/filenew.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/folder.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/folder_new.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/folder_yellow.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/invert_selection.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/lock.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/remove.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/resize_image.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/rotate_ccw.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/rotate_cw.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/select_none.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/show_panel.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/unlock.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/kfm.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/large_loader.gif [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/login.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/prompt.css [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/small_loader.gif [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/tableicons/asc.gif [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/tableicons/bg.gif [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/themes/default/tableicons/desc.gif [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/upload.php [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_add.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_add_blt.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_empty.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_empty_blt.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_full.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_full_blt.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/widget.js [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/widgets/trash/trash.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/widgets/trash/trash_blt.png [new file with mode: 0644]
ipf/admin/media/tiny_mce/plugins/kfm/widgets/trash/widget.js [new file with mode: 0644]
ipf/form/widget/htmlinput.php

diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/.htaccess b/ipf/admin/media/tiny_mce/plugins/kfm/.htaccess
new file mode 100644 (file)
index 0000000..248fab3
--- /dev/null
@@ -0,0 +1,28 @@
+<IfModule mod_deflate.c>
+       SetOutputFilter DEFLATE
+</IfModule>
+<IfModule mod_expires.c>
+       ExpiresActive On
+       ExpiresByType application/x-shockwave-flash "access plus 52 weeks"
+       ExpiresByType text/javascript "access plus 52 weeks"
+       ExpiresByType text/css "access plus 52 weeks"
+       ExpiresByType image/png "access plus 52 weeks"
+</IfModule>
+<IfModule mod_php4.c>
+       php_value magic_quotes_gpc off
+</IfModule>
+<IfModule mod_php5.c>
+       php_value magic_quotes_gpc off
+</IfModule>
+<IfModule mod_security.c>
+       SecFilterEngine Off
+       SecFilterScanPOST Off
+</IfModule>
+<IfModule sapi_apache2.c>
+       php_value magic_quotes_gpc off
+</IfModule>
+
+DirectoryIndex index.php
+FileETag none
+
+AddType "text/javascript;charset=UTF-8" .js
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/api/api.php b/ipf/admin/media/tiny_mce/plugins/kfm/api/api.php
new file mode 100644 (file)
index 0000000..917eff3
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+# see ../license.txt for licensing
+
+function kfm_api_createDirectory($parent,$name){
+       $r=kfm_createDirectory($parent,$name);
+       foreach($r['directories'] as $dir)if($dir[0]==$name)return $dir[2];
+       return 0;
+}
+function kfm_api_getDirectoryId($address){
+       global $kfmdb;
+       $arr=explode('/',$address);
+       $curdir=1;
+       if($arr[count($arr)-1]==''&&count($arr)>1)array_pop($arr);
+       foreach($arr as $n){
+               $r=db_fetch_row("select id from ".KFM_DB_PREFIX."directories where parent=".$curdir." and name='".sql_escape($n)."'");
+               if(!count($r))return 0;
+               $curdir=$r['id'];
+       }
+       return $curdir;
+}
+function kfm_api_removeFile($id){
+       $f=kfmFile::getInstance($id);
+       $p=$f->parent;
+       $f->delete();
+       return kfm_loadFiles($p);
+}
+$kfm_api_auth_override=1;
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/api/cms_hooks.php.dist b/ipf/admin/media/tiny_mce/plugins/kfm/api/cms_hooks.php.dist
new file mode 100644 (file)
index 0000000..ecd7013
--- /dev/null
@@ -0,0 +1,9 @@
+<?php
+# see ../license.txt for licensing
+#
+# copy this file to cms_hooks.php if you want to create your own functions
+
+function kfm_cmsHooks_allowedToDeleteFile($fid){
+       return true;
+}
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/api/config.php.dist b/ipf/admin/media/tiny_mce/plugins/kfm/api/config.php.dist
new file mode 100644 (file)
index 0000000..8a29866
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+# this file should be renamed to config.php if you want to override ../config.php with scripts and such.
+
+/*
+ THIS IS AN EXAMPLE
+
+
+session_start();
+include($_SERVER['DOCUMENT_ROOT'].'/config/config.php');
+//var_dump($_SESSION);
+if(!isset($_SESSION['system_auth'])||!isset($_SESSION['system_auth']['user']))exit('access denied!');
+{ # load config.ini
+       $c=array();
+       $f=file(APP_ROOT.'/application/config/config.ini');
+       foreach($f as $l){
+               $s=explode('=',$l);
+               if(count($s)!=2)continue;
+               $k=ltrim(rtrim($s[0]));
+               $v=ltrim(rtrim($s[1]));
+               if(!isset($c[$k]))$c[$k]=$v;
+       }
+}
+$kfm_userfiles_address='./uploads/'.$_SESSION['system_auth']['user']->uid;
+$kfm_userfiles_output=$kfm_userfiles_address.'/';
+$kfm_db_host=$c['db.config.host'];
+KFM_DB_PREFIX="kfm_".$_SESSION['system_auth']['user']->uid.'_';
+$kfm_db_name=$c['db.config.dbname'];
+$kfm_db_username=$c['db.config.username'];
+$kfm_db_password=$c['db.config.password'];
+$kfm_api_auth_override=1;
+*/
+
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/configuration.dist.php b/ipf/admin/media/tiny_mce/plugins/kfm/configuration.dist.php
new file mode 100644 (file)
index 0000000..17c17e5
--- /dev/null
@@ -0,0 +1,208 @@
+<?php
+/**
+ * KFM - Kae's File Manager
+ *
+ * configuration example file
+ *
+ * do not delete this file. copy it to configuration.php, remove the lines
+ *   you don't want to change, and edit the rest to your own needs.
+ *
+ * @category None
+ * @package  None
+ * @author   Kae Verens <kae@verens.com>
+ * @author   Benjamin ter Kuile <bterkuile@gmail.com>
+ * @license  docs/license.txt for licensing
+ * @link     http://kfm.verens.com/
+ */
+
+// user access details. all users may use get.php without logging in, but
+//   if the following details are filled in, then login will be required
+//   for the main KFM application
+// for more details, see http://kfm.verens.com/security
+$kfm_username = '';
+$kfm_password = '';
+
+// what type of database to use
+// values allowed: mysql, pgsql, sqlite, sqlitepdo
+$kfm_db_type = 'sqlitepdo';
+
+// the following options should only be filled if you are not using sqlite/sqlitepdo as the database
+$kfm_db_prefix   = 'kfm_';
+$kfm_db_host     = 'localhost';
+$kfm_db_name     = 'kfm';
+$kfm_db_username = 'username';
+$kfm_db_password = 'password';
+$kfm_db_port     = '';
+
+// where on the machine are the files located? if the first two characters are './', then the
+//   files are relative to the directory that KFM is in.
+// Here are some examples:
+// $kfm_userfiles_address = '/home/kae/userfiles'; # absolute address in Linux
+// $kfm_userfiles_address = 'D:/Files';            # absolute address in Windows
+// $kfm_userfiles_address = './uploads';           # relative address
+$kfm_userfiles_address = '/home/kae/Desktop/userfiles';
+
+// where should a browser look to find the files?
+// Note that this is usually the same as $kfm_userfiles_address (if it is relative), but could be different
+//   in the case that the server uses mod_rewrite or personal web-sites, etc
+// Use the value 'get.php' if you want to use the KFM file handler script to manage file downloads.
+// If you are not using get.php, this value must end in '/'.
+// Examples:
+//   $kfm_userfiles_output = 'http://thisdomain.com/files/';
+//   $kfm_userfiles_output = '/files/';
+//   $kfm_userfiles_output = 'http://thisdomain.com/kfm/get.php';
+//   $kfm_userfiles_output = '/kfm/get.php';
+$kfm_userfiles_output = '/userfiles/';
+
+// if you want to hide any panels, add them here as a comma-delimited string
+// for example, $kfm_hidden_panels = 'logs,file_details,file_upload,search,directory_properties';
+$kfm_hidden_panels = 'logs';
+
+// what happens if someone double-clicks a file or presses enter on one? use 'return' for FCKeditor
+// values allowed: download, return
+$kfm_file_handler = 'return';
+
+// if 'return' is chosen above, do you want to allow multiple file returns?
+$kfm_allow_multiple_file_returns = true;
+
+// directory in which KFM keeps its database and generated files
+// if this starts with '/', then the address is absolute. otherwise, it is relative to $kfm_userfiles_address.
+// $kfm_workdirectory = '.files';
+// $kfm_workdirectory = '/home/kae/files_cache';
+// warning: if you use the '/' method, then you must use the get.php method for $kfm_userfiles_output.
+$kfm_workdirectory = '.files';
+
+// maximum length of filenames in Icon mode. use 0 to turn this off, or enter the number of letters.
+$kfm_files_name_length_displayed = 20;
+
+// maximum length of filenames in Listmode. use 0 to turn this off, or enter the number of letters.
+$kfm_files_name_length_in_list = 0;
+
+// 1 = users are allowed to delete directories
+// 0 = users are not allowed to delete directories
+$kfm_allow_directory_delete = 1;
+
+// 1 = users are allowed to edit directories
+// 0 = users are not allowed to edit directories
+$kfm_allow_directory_edit = 1;
+
+// 1 = users are allowed to move directories
+// 0 = users are not allowed to move directories
+$kfm_allow_directory_move = 1;
+
+// 1 = users are allowed to create directories
+// 0 = user are not allowed create directories
+$kfm_allow_directory_create = 1;
+
+// 1 = users are allowed to create files
+// 0 = users are not allowed to create files
+$kfm_allow_file_create = 1;
+
+// 1 = users are allowed to delete files
+// 0 = users are not allowed to delete files
+$kfm_allow_file_delete = 1;
+
+// 1 = users are allowed to edit files
+// 0 = users are not allowed to edit files
+$kfm_allow_file_edit = 1;
+
+// 1 = users are allowed to move files
+// 0 = users are not allowed to move files
+$kfm_allow_file_move = 1;
+
+// 1 = users are allowed to upload files
+// 0 = user are not allowed upload files
+$kfm_allow_file_upload = 1;
+
+// use this array to ban dangerous files from being uploaded.
+$kfm_banned_extensions = array('asp','cfm','cgi','php','php3','php4','php5','phtm','pl','sh','shtm','shtml');
+
+// you can use regular expressions in this one.
+// for exact matches, use lowercase.
+// for regular expressions, use eithe '/' or '@' as the delimiter
+$kfm_banned_files = array('thumbs.db','/^\./');
+
+// you can use regular expressions in this one.
+// for exact matches, use lowercase.
+// for regular expressions, use eithe '/' or '@' as the delimiter
+$kfm_banned_folders = array('/^\./');
+
+// this array tells KFM what extensions indicate files which may be edited online.
+$kfm_editable_extensions = array('css','html','js','php','txt','xhtml','xml');
+
+// this array tells KFM what extensions indicate files which may be viewed online.
+// the contents of $kfm_editable_extensions will be added automatically.
+$kfm_viewable_extensions = array('sql','php');
+
+// 1 = users can only upload images
+// 0 = don't restrict the types of uploadable file
+$kfm_only_allow_image_upload = 0;
+
+// 0 = only errors will be logged
+// 1 = everything will be logged
+$kfm_log_level = 0;
+
+// use this array to show the order in which language files will be checked for
+$kfm_preferred_languages = array('en','de','da','es','fr','nl','ga');
+
+// themes are located in ./themes/
+// to use a different theme, replace 'default' with the name of the theme's directory.
+$kfm_theme = 'default';
+
+// use ImageMagick's 'convert' program?
+$kfm_use_imagemagick = 1;
+
+// where is the 'convert' program kept, if you have it installed?
+$kfm_imagemagick_path = '/usr/bin/convert';
+
+// show files in groups of 'n', where 'n' is a number (helps speed up files display - use low numbers for slow machines)
+$kfm_show_files_in_groups_of = 10;
+
+// should disabled links be shown (but grayed out and unclickable), or completely hidden?
+// you might use this if you want your users to not know what it is that's been disabled, for example.
+$kfm_show_disabled_contextmenu_links = 1;
+
+// multiple file uploads are handled through the external SWFUpload flash application.
+// this can cause difficulties on some systems, so if you have problems uploading, then disable this.
+$kfm_use_multiple_file_upload = 0;
+
+// seconds between slides in a slideshow
+$kfm_slideshow_delay = 4;
+
+// allow users to resize/rotate images
+$kfm_allow_image_manipulation = 1;
+
+// set root folder name
+// Set to foldername to use actual folder name or root when $kfm_user_root_folder is not set
+$kfm_root_folder_name = 'foldername';
+
+// if you are using a CMS and want to return the file's DB id instead of the URL, set this
+$kfm_return_file_id_to_cms = 0;
+
+//Permissions for uploaded files.  This only really needs changing if your
+//host has a weird permissions scheme.
+$kfm_default_upload_permission = '664';
+
+//Listview or icons
+$kfm_listview = 0;
+
+// how many files to attempt to draw at a time (use a low value for old client machines, and a higher value for newer machines)
+$kfm_show_files_in_groups_of = 10;
+
+// default directories. Separate with commas. These will be created if they don't already exist.
+// $kfm_default_directories='Documents,Music,Video';
+$kfm_default_directories='';
+
+// we would like to keep track of installations, to see how many there are, and what versions are in use.
+// if you do not want us to have this information, then set the following variable to '1'.
+$kfm_dont_send_metrics = 0;
+
+// hours to offset server time by.
+// for example, if the server is in GMT, and you are in Northern Territory, Australia, then the value to use is 9.5
+$kfm_server_hours_offset = 1;
+
+// 1=always move, 2=always copy, 3=give choice
+$kfm_drags_move_or_copy_files = 3;
+
+// allow files in the root directory
+$kfm_allow_files_in_root = 1;
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/configuration.php b/ipf/admin/media/tiny_mce/plugins/kfm/configuration.php
new file mode 100644 (file)
index 0000000..d3bf1f6
--- /dev/null
@@ -0,0 +1,209 @@
+<?php
+/**
+ * KFM - Kae's File Manager
+ *
+ * configuration example file
+ *
+ * do not delete this file. copy it to configuration.php, remove the lines
+ *   you don't want to change, and edit the rest to your own needs.
+ *
+ * @category None
+ * @package  None
+ * @author   Kae Verens <kae@verens.com>
+ * @author   Benjamin ter Kuile <bterkuile@gmail.com>
+ * @license  docs/license.txt for licensing
+ * @link     http://kfm.verens.com/
+ */
+
+// user access details. all users may use get.php without logging in, but
+//   if the following details are filled in, then login will be required
+//   for the main KFM application
+// for more details, see http://kfm.verens.com/security
+$kfm_username = '';
+$kfm_password = '';
+
+// what type of database to use
+// values allowed: mysql, pgsql, sqlite, sqlitepdo
+$kfm_db_type = 'sqlitepdo';
+
+// the following options should only be filled if you are not using sqlite/sqlitepdo as the database
+$kfm_db_prefix   = 'kfm_';
+$kfm_db_host     = 'localhost';
+$kfm_db_name     = '.kfm.sqlite';
+$kfm_db_username = 'username';
+$kfm_db_password = 'password';
+$kfm_db_port     = '';
+
+// where on the machine are the files located? if the first two characters are './', then the
+//   files are relative to the directory that KFM is in.
+// Here are some examples:
+// $kfm_userfiles_address = '/home/kae/userfiles'; # absolute address in Linux
+// $kfm_userfiles_address = 'D:/Files';            # absolute address in Windows
+// $kfm_userfiles_address = './uploads';           # relative address
+$kfm_userfiles_address = $_SERVER['DOCUMENT_ROOT'].'/media/upload';
+
+// where should a browser look to find the files?
+// Note that this is usually the same as $kfm_userfiles_address (if it is relative), but could be different
+//   in the case that the server uses mod_rewrite or personal web-sites, etc
+// Use the value 'get.php' if you want to use the KFM file handler script to manage file downloads.
+// If you are not using get.php, this value must end in '/'.
+// Examples:
+//   $kfm_userfiles_output = 'http://thisdomain.com/files/';
+//   $kfm_userfiles_output = '/files/';
+//   $kfm_userfiles_output = 'http://thisdomain.com/kfm/get.php';
+//   $kfm_userfiles_output = '/kfm/get.php';
+$kfm_userfiles_output = '/media/upload/';
+
+// if you want to hide any panels, add them here as a comma-delimited string
+// for example, $kfm_hidden_panels = 'logs,file_details,file_upload,search,directory_properties';
+$kfm_hidden_panels = 'logs';
+
+// what happens if someone double-clicks a file or presses enter on one? use 'return' for FCKeditor
+// values allowed: download, return
+$kfm_file_handler = 'return';
+
+// if 'return' is chosen above, do you want to allow multiple file returns?
+$kfm_allow_multiple_file_returns = true;
+
+// directory in which KFM keeps its database and generated files
+// if this starts with '/', then the address is absolute. otherwise, it is relative to $kfm_userfiles_address.
+// $kfm_workdirectory = '.files';
+// $kfm_workdirectory = '/home/kae/files_cache';
+// warning: if you use the '/' method, then you must use the get.php method for $kfm_userfiles_output.
+$kfm_workdirectory = '.kfm';
+
+// maximum length of filenames in Icon mode. use 0 to turn this off, or enter the number of letters.
+$kfm_files_name_length_displayed = 20;
+
+// maximum length of filenames in Listmode. use 0 to turn this off, or enter the number of letters.
+$kfm_files_name_length_in_list = 0;
+
+// 1 = users are allowed to delete directories
+// 0 = users are not allowed to delete directories
+$kfm_allow_directory_delete = 1;
+
+// 1 = users are allowed to edit directories
+// 0 = users are not allowed to edit directories
+$kfm_allow_directory_edit = 1;
+
+// 1 = users are allowed to move directories
+// 0 = users are not allowed to move directories
+$kfm_allow_directory_move = 1;
+
+// 1 = users are allowed to create directories
+// 0 = user are not allowed create directories
+$kfm_allow_directory_create = 1;
+
+// 1 = users are allowed to create files
+// 0 = users are not allowed to create files
+$kfm_allow_file_create = 1;
+
+// 1 = users are allowed to delete files
+// 0 = users are not allowed to delete files
+$kfm_allow_file_delete = 1;
+
+// 1 = users are allowed to edit files
+// 0 = users are not allowed to edit files
+$kfm_allow_file_edit = 1;
+
+// 1 = users are allowed to move files
+// 0 = users are not allowed to move files
+$kfm_allow_file_move = 1;
+
+// 1 = users are allowed to upload files
+// 0 = user are not allowed upload files
+$kfm_allow_file_upload = 1;
+
+// use this array to ban dangerous files from being uploaded.
+$kfm_banned_extensions = array('asp','cfm','cgi','php','php3','php4','php5','phtm','pl','sh','shtm','shtml');
+
+// you can use regular expressions in this one.
+// for exact matches, use lowercase.
+// for regular expressions, use eithe '/' or '@' as the delimiter
+$kfm_banned_files = array('thumbs.db','/^\./');
+
+// you can use regular expressions in this one.
+// for exact matches, use lowercase.
+// for regular expressions, use eithe '/' or '@' as the delimiter
+$kfm_banned_folders = array('/^\./');
+
+// this array tells KFM what extensions indicate files which may be edited online.
+$kfm_editable_extensions = array('css','html','js','php','txt','xhtml','xml');
+
+// this array tells KFM what extensions indicate files which may be viewed online.
+// the contents of $kfm_editable_extensions will be added automatically.
+$kfm_viewable_extensions = array('sql','php');
+
+// 1 = users can only upload images
+// 0 = don't restrict the types of uploadable file
+$kfm_only_allow_image_upload = 0;
+
+// 0 = only errors will be logged
+// 1 = everything will be logged
+$kfm_log_level = 0;
+
+// use this array to show the order in which language files will be checked for
+//$kfm_preferred_languages = array('en','de','da','es','fr','nl','ga');
+$kfm_preferred_languages = array('en');
+
+// themes are located in ./themes/
+// to use a different theme, replace 'default' with the name of the theme's directory.
+$kfm_theme = 'default';
+
+// use ImageMagick's 'convert' program?
+$kfm_use_imagemagick = 0;
+
+// where is the 'convert' program kept, if you have it installed?
+$kfm_imagemagick_path = '/usr/local/bin/convert';
+
+// show files in groups of 'n', where 'n' is a number (helps speed up files display - use low numbers for slow machines)
+$kfm_show_files_in_groups_of = 10;
+
+// should disabled links be shown (but grayed out and unclickable), or completely hidden?
+// you might use this if you want your users to not know what it is that's been disabled, for example.
+$kfm_show_disabled_contextmenu_links = 1;
+
+// multiple file uploads are handled through the external SWFUpload flash application.
+// this can cause difficulties on some systems, so if you have problems uploading, then disable this.
+$kfm_use_multiple_file_upload = 0;
+
+// seconds between slides in a slideshow
+$kfm_slideshow_delay = 4;
+
+// allow users to resize/rotate images
+$kfm_allow_image_manipulation = 0;
+
+// set root folder name
+// Set to foldername to use actual folder name or root when $kfm_user_root_folder is not set
+$kfm_root_folder_name = '/media/upload';
+
+// if you are using a CMS and want to return the file's DB id instead of the URL, set this
+$kfm_return_file_id_to_cms = 0;
+
+//Permissions for uploaded files.  This only really needs changing if your
+//host has a weird permissions scheme.
+$kfm_default_upload_permission = '664';
+
+//Listview or icons
+$kfm_listview = 0;
+
+// how many files to attempt to draw at a time (use a low value for old client machines, and a higher value for newer machines)
+$kfm_show_files_in_groups_of = 10;
+
+// default directories. Separate with commas. These will be created if they don't already exist.
+// $kfm_default_directories='Documents,Music,Video';
+$kfm_default_directories='';
+
+// we would like to keep track of installations, to see how many there are, and what versions are in use.
+// if you do not want us to have this information, then set the following variable to '1'.
+$kfm_dont_send_metrics = 0;
+
+// hours to offset server time by.
+// for example, if the server is in GMT, and you are in Northern Territory, Australia, then the value to use is 9.5
+$kfm_server_hours_offset = -5;
+
+// 1=always move, 2=always copy, 3=give choice
+$kfm_drags_move_or_copy_files = 3;
+
+// allow files in the root directory
+$kfm_allow_files_in_root = 1;
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/docs/license.txt b/ipf/admin/media/tiny_mce/plugins/kfm/docs/license.txt
new file mode 100644 (file)
index 0000000..eb92bf9
--- /dev/null
@@ -0,0 +1,9 @@
+Copyright (c) 2006, Kae Verens (kae@verens.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 KFM 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.
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/docs/readme.txt b/ipf/admin/media/tiny_mce/plugins/kfm/docs/readme.txt
new file mode 100644 (file)
index 0000000..c68eb53
--- /dev/null
@@ -0,0 +1,17 @@
+KFM - Kae's File Manager
+
+LICENSE and VERSION
+see version.txt for version
+see license.txt for licensing
+
+INSTALLATION
+http://kfm.verens.com/documentation
+
+INFORMATION
+http://kfm.verens.com/
+
+BUGS AND FEATURES
+http://mantis.verens.com/
+
+FORUM
+http://kfm.verens.com/phpBB3/
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/docs/version.txt b/ipf/admin/media/tiny_mce/plugins/kfm/docs/version.txt
new file mode 100644 (file)
index 0000000..7e32cd5
--- /dev/null
@@ -0,0 +1 @@
+1.3
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/fckplugin.js b/ipf/admin/media/tiny_mce/plugins/kfm/fckplugin.js
new file mode 100644 (file)
index 0000000..a1f1aae
--- /dev/null
@@ -0,0 +1,3 @@
+// see docs/license.txt for licensing
+var a,b=['Link','Image','Flash'],c,d=['Browser','Upload'];
+for(a in b)for(c in d)FCKConfig[b[a]+d[c]+'URL']=FCKConfig.BasePath+'plugins/kfm/index.php?lang='+FCKConfig.DefaultLanguage+'&kfm_caller_type=fck&type='+b[a];
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/get.php b/ipf/admin/media/tiny_mce/plugins/kfm/get.php
new file mode 100644 (file)
index 0000000..9b2a44f
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+/**
+ * KFM - Kae's File Manager
+ *
+ * get.php - retrieves a specified file
+ * can also resize an image on demand
+ *
+ * @category None
+ * @package  None
+ * @author   Kae Verens <kae@verens.com>
+ * @author   Benjamin ter Kuile <bterkuile@gmail.com>
+ * @license  docs/license.txt for licensing
+ * @link     http://kfm.verens.com/
+ */
+require_once 'initialise.php';
+if (isset($_SERVER['REDIRECT_QUERY_STRING'])&&$_SERVER['REDIRECT_QUERY_STRING']) {
+    $arr = explode(',', $_SERVER['REDIRECT_QUERY_STRING']);
+    foreach ($arr as $r) {
+        $arr2           = explode('=', $r);
+        $_GET[$arr2[0]] = $arr2[1];
+    }
+}
+// { rebuild $_GET (in case it's been mangled by something)
+$uri   = $_SERVER['REQUEST_URI'];
+$uri2  = explode('?', $uri);
+$parts = explode('&', $uri2[1]);
+foreach ($parts as $part) {
+    $arr = explode('=', $part);
+    if (!(count($arr)>1)) continue;
+    list($varname, $varval) = $arr;
+    $_GET[$varname]         = urldecode($varval);
+}
+// }
+$id = $_GET['id'];
+if (!is_numeric($id)) {
+    echo kfm_lang('errorInvalidID');
+    exit;
+}
+$extension = 'unknown';
+if (isset($_GET['type'])&&$_GET['type']=='thumb') {
+    $path = WORKPATH.'thumbs/'.$id;
+    $name = $id;
+} else {
+    if (isset($_GET['width'])&&isset($_GET['height'])) {
+        $width  = $_GET['width'];
+        $height = $_GET['height'];
+        $image  = kfmImage::getInstance($id);
+        if (!$image) {
+            echo kfm_lang('errorFileIDNotFound', $id);
+            exit;
+        }
+                               if($width>$image->width)$width=$image->width;
+                               if($height>$image->height)$height=$image->height;
+        $image->setThumbnail($width, $height);
+        $name      = $image->thumb_id;
+        $path      = $image->thumb_path;
+        $extension = $image->getExtension();
+    } else {
+        $file = kfmFile::getInstance($id);
+        if (!$file) {
+            echo kfm_lang('errorFileIDNotFound', $id);
+            exit;
+        }
+        $path      = $file->path;
+        $name      = $file->name;
+        $extension = $file->getExtension();
+    }
+}
+// { headers
+if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) $name = preg_replace('/\./', '%2e', $name, substr_count($name, '.')-1);
+@set_time_limit(0);
+header('Cache-Control: max-age = 2592000');
+header('Expires-Active: On');
+header('Expires: Fri, 1 Jan 2500 01:01:01 GMT');
+header('Pragma:');
+header('Content-Length: '.(string)(filesize($path)));
+if (isset($_GET['forcedownload'])) {
+    header('Content-Type: force/download');
+    header('Content-Disposition: attachment; filename="'.$name.'"');
+} else header('Content-Type: '.get_mimetype($extension));
+header('Content-Transfer-Encoding: binary');
+// }
+if ($file = fopen($path, 'rb')) { // send file
+    while ((!feof($file))&&(connection_status()==0)) {
+        print(fread($file, 1024*8));
+        flush();
+    }
+    fclose($file);
+}
+return((connection_status()==0) and !connection_aborted());
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/i/bg-black-75.png b/ipf/admin/media/tiny_mce/plugins/kfm/i/bg-black-75.png
new file mode 100644 (file)
index 0000000..f59e4fe
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/i/bg-black-75.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/db.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/db.php
new file mode 100644 (file)
index 0000000..2a4de02
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+class DB{
+       var $db=0;
+       var $dbtype='';
+       function DB($dsn=array()){
+               switch($dsn['type']){
+                       case 'sqlitepdo':{
+                               require(KFM_BASE_PATH.'includes/db.sqlite.pdo.php');
+                               $this->db=new DB_SQLite_PDO($dsn);
+                               $db_defined=1;
+                               break;
+                       }
+                       default:{
+                               exit('error: unknown database type "'.$dsn['type'].'"');
+                       }
+               }
+       }
+       function __construct($dsn=array()){
+               $this->DB($dsn);
+       }
+       function exec($query){
+               $this->db->query($query);
+       }
+       function fetchAll($query){
+               return $this->db->fetchAll($query);
+       }
+       function fetchRow($query){
+               return $this->db->fetchRow($query);
+       }
+       function lastInsertId($name=''){
+               return $this->db->lastInsertId($name);
+       }
+       function query($query){
+               return $this->db->query($query);
+       }
+}
+function db_fetch_all($query){
+       global $kfm_db_type,$kfmdb;
+       if($kfm_db_type=='sqlitepdo'){
+               return $kfmdb->fetchAll($query);
+       }
+       $q=$kfmdb->query($query);
+       return $q->fetchAll();
+}
+function db_fetch_row($query){
+       global $kfm_db_type,$kfmdb;
+       if($kfm_db_type=='sqlitepdo'){
+               return $kfmdb->fetchRow($query);
+       }
+       $q=$kfmdb->query($query);
+       if(PEAR::isError($q))die('alert("'.$q->getMessage().'\n'.$query.'")');
+       return $q->fetchRow();
+}
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/db.sqlite.pdo.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/db.sqlite.pdo.php
new file mode 100644 (file)
index 0000000..c97f6ba
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+class DB_SQLite_PDO{
+       var $connection=0;
+       function __construct($dsn=array()){
+               if(!isset($dsn['database']))exit('no SQLite database set in configuration');
+               try {
+                       $db=new PDO('sqlite:'.$dsn['database']);
+                       $this->connection=$db;
+               } catch (PDOException $e) {
+                       print "Error!: " . $e->getMessage();
+                       die();
+               }
+       }
+       function fetchAll($query){
+               $sth=$this->connection->prepare($query);
+               if(!$sth)return false;
+               $sth->execute();
+               return $sth->fetchAll();
+       }
+       function fetchRow($query){
+               $sth=$this->connection->prepare($query);
+               if(!$sth)return false;
+               $sth->execute();
+               return $sth->fetch();
+       }
+       function lastInsertId($name=''){
+               return $this->connection->lastInsertId($name);
+       }
+       function query($query){
+               return $this->connection->exec($query);
+       }
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/directories.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/directories.php
new file mode 100644 (file)
index 0000000..feeada8
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+function _createDirectory($parent,$name){
+       global $kfm_allow_directory_create;
+       if(!$kfm_allow_directory_create)return 'error: '.kfm_lang('permissionDeniedCreateDirectory');
+       $dir=kfmDirectory::getInstance($parent);
+       $dir->createSubdir($name);
+       if($dir->hasErrors()) return $dir->getErrors();
+       return kfm_loadDirectories($parent);
+}
+function _deleteDirectory($id,$recursive=0){
+       $dir=kfmDirectory::getInstance($id);
+       $dir->delete();
+       return kfm_loadDirectories($dir->pid,$id);
+}
+function _getDirectoryDbInfo($id){
+       global $kfmdb;
+       if(!isset($_GLOBALS['cache_directories'][$id])){
+               $_GLOBALS['cache_directories'][$id]=db_fetch_row("select * from ".KFM_DB_PREFIX."directories where id=".$id);
+       }
+       return $_GLOBALS['cache_directories'][$id];
+}
+function _getDirectoryParents($pid,$type=1){
+       # type is 1:absolute, 2:relative to domain
+       if($pid<2)return $GLOBALS['rootdir'];
+       $db=_getDirectoryDbInfo($pid);
+       return _getDirectoryParents($db['parent'],$type).$db['name'].'/';
+}
+function _getDirectoryParentsArr($dir,$path=array()){
+       $db=_getDirectoryDbInfo($dir);
+       if(!$db)return $path;
+       $pdir=$db['parent'];
+       array_unshift($path,$pdir);
+       if($pdir>1)$path=_getDirectoryParentsArr($pdir,$path);
+       return $path;
+}
+function _loadDirectories($pid,$oldpid=0){
+       global $kfmdb, $kfm_banned_folders;
+       $dir=kfmDirectory::getInstance($pid);
+       $pdir=str_replace($GLOBALS['rootdir'],'',$dir->path);
+       $directories=array();
+       foreach($dir->getSubdirs() as $subDir)$directories[]=array($subDir->name,$subDir->hasSubdirs(),$subDir->id);
+       sort($directories);
+       return array(
+               'parent'=>$pid,
+               'oldpid'=>$oldpid,
+               'reqdir'=>$pdir,
+               'directories'=>$directories,
+               'properties'=>$dir->getProperties()
+       );
+}
+function _moveDirectory($from,$to){
+       global $kfm_allow_directory_move;
+       if(!$kfm_allow_directory_move)return 'error: '.kfm_lang('permissionDeniedMoveDirectory');
+       $dir=kfmDirectory::getInstance($from);
+       $dir->moveTo($to);
+       if($dir->hasErrors()) return $dir->getErrors();
+       return _loadDirectories(1);
+}
+function _renameDirectory($fid,$newname){
+       global $kfm_allow_directory_edit;
+       if(!$kfm_allow_directory_edit)return 'error: '.kfm_lang('permissionDeniedEditDirectory');
+       $dir=kfmDirectory::getInstance($fid);
+       $dir->rename($newname);
+       return _loadDirectories($dir->pid);
+}
+function _rmdir($pid){
+       return _deleteDirectory($pid);
+}
+function kfm_rmMixed($files=array(), $directories=array()){
+       $filecount=0;
+       $dircount=0;
+       foreach($files as $fid){
+               $file=kfmFile::getInstance($fid);
+               if($file->delete())$filecount++;
+       }
+       foreach($directories as $did){
+               $dir=new kfmDirectory($did);
+               if($dir->delete())$dircount++;
+       }
+}      
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/directory.class.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/directory.class.php
new file mode 100644 (file)
index 0000000..6dd1208
--- /dev/null
@@ -0,0 +1,220 @@
+<?php
+$kfmDirectoryInstances=array();
+class kfmDirectory extends kfmObject{
+       var $subDirs=array();
+       function kfmDirectory($id=1){
+               parent::__construct();
+               $this->id=$id;
+               if(!$id)return;
+               $res=db_fetch_row("SELECT * FROM ".KFM_DB_PREFIX."directories WHERE id=".$this->id);
+               if(!$res)return $this->id=0;
+               $this->name=$res['name'];
+               $this->pid=$res['parent'];
+               $this->path=$this->getPath();
+       }
+       function __construct($id=1){
+               $this->kfmDirectory($id);
+       }
+       function addSubdirToDb($name){
+               global $kfm;
+               $sql="INSERT INTO ".KFM_DB_PREFIX."directories (name,parent) VALUES('".sql_escape($name)."',".$this->id.")";
+               return $kfm->db->exec($sql);
+       }
+       function checkAddr($addr){
+               return (
+                       strpos($addr,'..')===false&&
+                       strpos($addr,'.')!==0&&
+                       strpos($addr,'/.')===false);
+       }
+       function createSubdir($name){
+               if(!$GLOBALS['kfm_allow_directory_create'])return $this->error(kfm_lang('permissionDeniedCreateDirectory'));
+               $physical_address=$this->path.$name;
+               $short_version=str_replace($GLOBALS['rootdir'],'',$physical_address);
+               if(!$this->checkAddr($physical_address)){
+                       $this->error(kfm_lang('illegalDirectoryName',$short_version));
+                       return false;
+               }
+               if(file_exists($physical_address)){
+                       $this->error(kfm_lang('alreadyExists',$short_version));
+                       return false;
+               }
+               mkdir($physical_address);
+               if(!file_exists($physical_address)){
+                       $this->error(kfm_lang('failedCreateDirectoryCheck',$name));
+                       return false;
+               }
+               return $this->addSubdirToDb($name);
+       }
+       function delete(){
+               global $kfm;
+               if(!$GLOBALS['kfm_allow_directory_delete'])return $this->error(kfm_lang('permissionDeniedDeleteDirectory'));
+               $files=$this->getFiles();
+               foreach($files as $f){
+                       if(!$f->delete())return false;
+               }
+               $subdirs=$this->getSubdirs();
+               foreach($subdirs as $subdir){
+                       if(!$subdir->delete())return false;
+               }
+               rmdir($this->path);
+               if(is_dir($this->path))return $this->error('failed to delete directory '.$this->path);
+               $kfm->db->exec("delete from ".KFM_DB_PREFIX."directories where id=".$this->id);
+               return true;
+       }
+       function getFiles(){
+               $this->handle=opendir($this->path);
+               if(!$this->handle)return $this->error('unable to open directory');
+               $filesdb=db_fetch_all("select * from ".KFM_DB_PREFIX."files where directory=".$this->id);
+               $fileshash=array();
+               if(is_array($filesdb))foreach($filesdb as $r)$fileshash[$r['name']]=$r['id'];
+               $files=array();
+               while(false!==($filename=readdir($this->handle))){
+                       if(is_file($this->path.$filename)&&kfmFile::checkName($filename)){
+                               if(!isset($fileshash[$filename]))$fileshash[$filename]=kfmFile::addToDb($filename,$this->id);
+                               $file=kfmFile::getInstance($fileshash[$filename]);
+                               if(!$file)continue;
+                               if($file->isImage())$file=kfmImage::getInstance($fileshash[$filename]);
+                               $files[]=$file;
+                               unset($fileshash[$filename]);
+                       }
+               }
+               closedir($this->handle);
+               return $files;
+       }
+       function getInstance($id=1){
+               global $kfmDirectoryInstances;
+               if(!isset($kfmDirectoryInstances[$id])){
+                       $dir=new kfmDirectory($id);
+                       if($dir->id==0)return false;
+                       $kfmDirectoryInstances[$id]=$dir;
+               }
+               return $kfmDirectoryInstances[$id];
+       }
+       function getPath(){
+               $pathTmp=$this->name.'/';
+               $pid=$this->pid;
+               if(!$pid)return $GLOBALS['rootdir'];
+               while($pid>1){
+                       $p=kfmDirectory::getInstance($pid);
+                       $pathTmp=$p->name.'/'.$pathTmp;
+                       $pid=$p->pid;
+               }
+               return $GLOBALS['rootdir'].$pathTmp;
+       }
+       function getProperties(){
+               return array(
+                       'allowed_file_extensions' => '',
+                       'name'                    => $this->name,
+                       'path'                    => str_replace($_SERVER['DOCUMENT_ROOT'],'',$this->path),
+                       'parent'                  => $this->pid,
+                       'is_writable'             => $this->isWritable()
+               );
+       }
+       function getSubdirs($oldstyle=false){
+               global $kfm;
+               $this->handle=opendir($this->path);
+               $dirsdb=db_fetch_all("select id,name from ".KFM_DB_PREFIX."directories where parent=".$this->id);
+               $dirshash=array();
+               if(is_array($dirsdb))foreach($dirsdb as $r)$dirshash[$r['name']]=$r['id'];
+               $directories=array();
+               while(false!==($file=readdir($this->handle))){
+                       if(is_dir($this->path.$file)&&$this->checkName($file)){
+                               if(!isset($dirshash[$file])){
+                                       $this->addSubdirToDb($file);
+                                       $dirshash[$file]=$kfm->db->lastInsertId(KFM_DB_PREFIX.'directories','id');
+                               }
+                               $directories[]=kfmDirectory::getInstance($dirshash[$file]);
+                               unset($dirshash[$file]);
+                       }
+               }
+               closedir($this->handle);
+               return $directories;
+       }
+       function hasSubdirs(){
+               $this->handle=opendir($this->path);
+               if($this->handle){
+                       while(false!==($file=readdir($this->handle))){
+                               if($this->checkName($file) && is_dir($this->path.$file)) return true;
+                       }
+                       closedir($this->handle);
+                       return false;
+               }else{
+                       $this->error('Directory could not be opened');
+               }
+       }
+       function getSubdir($dirname){
+               $res=db_fetch_row('select id from '.KFM_DB_PREFIX.'directories where name="'.$dirname.'" and parent='.$this->id);
+               if($res)return kfmDirectory::getInstance($res['id']);
+               return false;
+       }
+       function isWritable(){
+               return is_writable($this->path);        
+       }
+       function moveTo($newParent){
+               global $kfm;
+               if(is_numeric($newParent))$newParent=kfmDirectory::getInstance($newParent);
+               { # check for errors
+                       if(!$GLOBALS['kfm_allow_directory_move'])return $this->error(kfm_lang('permissionDeniedMoveDirectory'));
+                       if(strpos($newParent->path,$this->path)===0) return $this->error(kfm_lang('cannotMoveIntoSelf'));
+                       if(file_exists($newParent->path.$this->name))return $this->error(kfm_lang('alreadyExists',$newParent->path.$this->name));
+                       if(!$newParent->isWritable())return $this->error(kfm_lang('isNotWritable',$newParent->path));
+               }
+               { # do the move and check that it was successful
+                       rename($this->path,$newParent->path.'/'.$this->name);
+                       if(!file_exists($newParent->path.$this->name))return $this->error(kfm_lang('couldNotMoveDirectory',$this->path,$newParent->path.$this->name));
+               }
+               { # update database and kfmDirectory object
+                       $kfm->db->exec("update ".KFM_DB_PREFIX."directories set parent=".$newParent->id." where id=".$this->id) or die('error: '.print_r($kfmdb->errorInfo(),true));
+                       $this->pid=$newParent->id;
+                       $this->path=$this->getPath();
+               }
+       }
+       function rename($newname){
+               global $kfm,$kfm_allow_directory_edit,$kfmDirectoryInstances;
+               if(!$GLOBALS['kfm_allow_directory_edit'])return $this->error(kfm_lang('permissionDeniedEditDirectory'));
+               if(!$this->isWritable())return $this->error(kfm_lang('permissionDeniedRename',$this->name));
+               if(!$this->checkAddr($newname))return $this->error(kfm_lang('cannotRenameFromTo',$this->name,$newname));
+               $parent=kfmDirectory::getInstance($this->pid);
+               if(file_exists($parent->path.$newname))return $this->error(kfm_lang('aDirectoryNamedAlreadyExists',$newname));
+               rename($this->path,$parent->path.$newname);
+               if(file_exists($this->path))return $this->error(kfm_lang('failedRenameDirectory'));
+               $kfm->db->query("update ".KFM_DB_PREFIX."directories set name='".sql_escape($newname)."' where id=".$this->id);
+               $this->name=$newname;
+               $this->path=$this->getPath();
+               $kfmDirectoryInstances[$this->id]=$this;
+       }
+       function checkName($file=false){
+               if($file===false)$file=$this->name;
+               if(trim($file)==''|| trim($file)!=$file)return false;
+               if($file=='.'||$file=='..')return false;
+               foreach($GLOBALS['kfm_banned_folders'] as $ban){
+                       if(($ban[0]=='/' || $ban[0]=='@')&&preg_match($ban,$file))return false;
+                       elseif($ban==strtolower(trim($file)))return false;
+               }
+               if(isset($GLOBALS['kfm_allowed_folders']) && is_array($GLOBALS['kfm_allowed_folders'])){
+                       foreach($GLOBALS['kfm_allowed_folders'] as $allow){
+                               if($allow[0]=='/' || $allow[0]=='@'){
+                                       if(preg_match($allow, $file))return true;
+                               }else if($allow==strtolower($file)) return true;
+                       }
+                       return false;
+               }
+               return true;
+       }
+       function addFile($file){
+               if(!$GLOBALS['kfm_allow_file_create'])return $this->error(kfm_lang('permissionDeniedCreateFile'));
+               if(is_numeric($file))$file=kfmFile::getInstance($file);
+               if(!$this->isWritable())return $this->error(kfm_lang('fileNotCreatedDirUnwritable',$file->name));
+               copy($file->path,$this->path.'/'.$file->name);
+               $id=$file->addToDb($file->name,$this->id);
+               if($file->isImage()){
+                       $file=kfmImage::getInstance($file->id);
+                       $newFile=kfmImage::getInstance($id);
+                       $newFile->setCaption($file->caption);
+               }
+               else $newFile=kfmFile::getInstance($id);
+               $newFile->setTags($file->getTags());
+               return true;
+       }
+}
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/file.class.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/file.class.php
new file mode 100644 (file)
index 0000000..2b1878b
--- /dev/null
@@ -0,0 +1,277 @@
+<?php
+$fileInstances=array();
+/**
+ * Base file class
+ */
+class kfmFile extends kfmObject{
+       var $ctime='';
+       var $directory='';
+       var $exists=0;
+       var $id=-1;
+       var $mimetype='';
+       var $name='';
+       var $parent=0;
+       var $path='';
+       var $size=0;
+       var $type;
+       var $writable=false;
+       function kfmFile(){
+               global $kfm;
+               if(func_num_args()==1){
+                       $this->id=(int)func_get_arg(0);
+                       parent::kfmObject();
+                       $filedata=db_fetch_row("SELECT id,name,directory FROM ".KFM_DB_PREFIX."files WHERE id=".$this->id);
+                       $this->name=$filedata['name'];
+                       $this->parent=$filedata['directory'];
+                       $dir=kfmDirectory::getInstance($this->parent);
+                       $this->directory=$dir->path;
+                       $this->path=$dir->path.'/'.$filedata['name'];
+                       if(!$this->exists()){
+//                             $this->error(kfm_lang('File cannot be found')); // removed because it is causing false errors
+                               $this->delete();
+                               return false;
+                       }
+                       $this->writable=$this->isWritable();
+                       $this->ctime=filemtime($this->path)+$GLOBALS['kfm_server_hours_offset']*3600;
+                       $this->modified=strftime($kfm->setting('date_format').' '.$kfm->setting('time_format'),filemtime($this->path));
+                       $mimetype=get_mimetype($this->path);
+                       $pos=strpos($mimetype,';');
+                       $this->mimetype=($pos===false)?$mimetype:substr($mimetype,0,$pos);
+                       $this->type=trim(substr(strstr($this->mimetype,'/'),1));
+               }
+       }
+
+       /**
+        * Deletes the file
+        * @return bool true opon success, false on error
+        */
+       function delete(){
+               global $kfm,$kfm_allow_file_delete;
+               if(!$kfm_allow_file_delete)return $this->error(kfm_lang('permissionDeniedDeleteFile'));
+               if(!kfm_cmsHooks_allowedToDeleteFile($this->id))return $this->error(kfm_lang('CMSRefusesFileDelete',$this->path));
+               if($this->exists() && !$this->writable)return $this->error(kfm_lang('fileNotMovableUnwritable',$this->name));
+               if(!$this->exists() || unlink($this->path))$kfm->db->exec("DELETE FROM ".KFM_DB_PREFIX."files WHERE id=".$this->id);
+               else return $this->error(kfm_lang('failedDeleteFile',$this->name));
+               return true;
+       }
+
+       /**
+        * Checks if the file exists
+        * @return bool
+        * */
+       function exists(){
+               if($this->exists)return $this->exists;
+               $this->exists=file_exists($this->path);
+               return $this->exists;
+       }
+
+       /**
+        * Returns the file contents or false on error
+        */
+       function getContent(){
+               return ($this->id==-1)?false:utf8_encode(file_get_contents($this->path));
+       }
+
+       /**
+        * Function that returns the extension of the file.
+        * if a parameter is given, the extension of that parameters is returned
+        * returns false on error.
+        */
+       function getExtension(){
+               if(func_num_args()==1){
+                       $filename=func_get_arg(0);
+               }else{
+                       if($this->id==-1)return false;
+                       $filename=$this->name;
+               }
+               $dotext=strrchr($filename,'.');
+               if($dotext === false) return false;
+               return strtolower(substr($dotext,1));
+       }
+       /**
+        * Returns the url of the file as specified by the configuration
+        */
+       function getUrl($x=0,$y=0){
+               global $rootdir, $kfm_userfiles_output,$kfm_workdirectory;
+               $cwd=$this->directory.'/'==$rootdir?'':str_replace($rootdir,'',$this->directory);
+               if(!$this->exists())return 'javascript:alert("missing file")';
+               if(preg_replace('/.*(get\.php)$/','$1',$kfm_userfiles_output)=='get.php'){
+                       if($kfm_userfiles_output=='get.php')$url=preg_replace('/\/[^\/]*$/','/get.php?id='.$this->id.GET_PARAMS,$_SERVER['REQUEST_URI']);
+                       else $url=$kfm_userfiles_output.'?id='.$this->id;
+                       if($x&&$y)$url.='&width='.$x.'&height='.$y;
+               }
+               else{
+                       if($this->isImage()&&$x&&$y){
+                               $img=kfmImage::getInstance($this);
+                               $img->setThumbnail($x,$y);
+                               return $kfm_userfiles_output.$kfm_workdirectory.'/thumbs/'.$img->thumb_id;
+                       }
+                       else $url=$kfm_userfiles_output.'/'.$cwd.'/'.$this->name; # TODO: check this line - $cwd may be incorrect if the requested file is from a search
+               }
+               return preg_replace('/([^:])\/{2,}/','$1/',$url);
+       }
+
+       /**
+        * Returns the file instance. This is preferred above new kfmFile($id)
+        * @param int $file_id
+        * @return Object file or image
+        */
+       function getInstance($id=0){
+               global $fileInstances;
+               if(!$id)return false;
+               if(is_object($id))$id=$id->id;
+               if(!isset($fileInstances[$id]))$fileInstances[$id]=new kfmFile($id);
+               if($fileInstances[$id]->isImage())return kfmImage::getInstance($id);
+               return $fileInstances[$id];
+       }
+
+       /**
+        * retunrs the file size
+        */
+       function getSize(){
+               if(!$this->size)$this->size=filesize($this->path);
+               return $this->size;
+       }
+
+       /**
+        * Get the tags of the file
+        * @return Array
+        */
+       function getTags(){
+               $arr=array();
+               $tags=db_fetch_all("select tag_id from ".KFM_DB_PREFIX."tagged_files where file_id=".$this->id);
+               foreach($tags as $r)$arr[]=$r['tag_id'];
+               return $arr;
+       }
+
+       /**
+        * Check of file is an image
+        * @return bool
+        */
+       function isImage(){
+               return in_array($this->getExtension(),array('jpg', 'jpeg', 'gif', 'png', 'bmp'));
+       }
+
+       /**
+        * Check if the file is writable
+        * @return bool true when writable, false if not
+        */
+       function isWritable(){
+               return (($this->id==-1)||!is_writable($this->path))?false:true;
+       }
+
+       /**
+        * Moves the file
+        * @param int $new_directoryparent_id
+        */
+       function move($dir_id){
+               global $kfmdb,$kfm_allow_files_in_root;
+               if($dir_id==1 && !$kfm_allow_files_in_root)return $this->error('Cannot move files to the root directory');
+               if(!$this->writable)return $this->error(kfm_lang('fileNotMovableUnwritable',$this->name));
+               $dir=kfmDirectory::getInstance($dir_id);
+               if(!$dir)return $this->error(kfm_lang('failedGetDirectoryObject'));
+               if(!rename($this->path,$dir->path.'/'.$this->name))return $this->error(kfm_lang('failedMoveFile',$this->name));
+               $q=$kfmdb->query("update ".KFM_DB_PREFIX."files set directory=".$dir_id." where id=".$this->id);
+       }
+
+       /**
+        * Rename the file
+        * @param string $newName new file name
+        */
+       function rename($newName){
+               global $kfm,$kfm_allow_file_edit;
+               if(!$kfm_allow_file_edit)return $this->error(kfm_lang('permissionDeniedEditFile'));
+               if(!kfm_checkAddr($newName))return $this->error(kfm_lang('cannotRenameFromTo',$this->name,$newName));
+               $newFileAddress=$this->directory.$newName;
+               if(file_exists($newFileAddress))return $this->error(kfm_lang('fileAlreadyExists'));
+               rename($this->path,$newFileAddress);
+               $this->name=$newName;
+               $this->path=$newFileAddress;
+               $kfm->db->query("UPDATE ".KFM_DB_PREFIX."files SET name='".sql_escape($newName)."' WHERE id=".$this->id);
+       }
+
+       /**
+        * Write content to the file
+        * @param mixed $content
+        */
+       function setContent($content){
+               global $kfm_allow_file_edit;
+               if(!$kfm_allow_file_edit)return $this->error(kfm_lang('permissionDeniedEditFile'));
+               $result=file_put_contents($this->path,utf8_decode($content));
+               if(!$result)return $this->error(kfm_lang('errorSettingFileContent'));
+               return true;
+       }
+
+       /**
+        * Set tags of the file
+        * @param array $tags
+        */
+       function setTags($tags){
+               global $kfm;
+               if(!count($tags))return;
+               $kfm->db->exec("DELETE FROM ".KFM_DB_PREFIX."tagged_files WHERE file_id=".$this->id);
+               foreach($tags as $tag)$kfm->db->exec("INSERT INTO ".KFM_DB_PREFIX."tagged_files (file_id,tag_id) VALUES(".$this->id.",".$tag.")");
+       }
+
+       /**
+        * Get the filezise in a human-readable way
+        * @param int $size optional
+        * @return string $size
+        */
+       function size2str(){
+               $size=func_num_args()?func_get_arg(0):$this->getSize();
+               if(!$size)return '0';
+               $format=array("B","KB","MB","GB","TB","PB","EB","ZB","YB");
+               $n=floor(log($size)/log(1024));
+               return $n?round($size/pow(1024,$n),1).' '.$format[$n]:'0 B';
+       }
+
+       /**
+        * Add the file to the database
+        * @param string $filename name of the file
+        * @param int $directory_id id of the directory in which the file is located
+        * @return int $file_id id assigned to the file
+        */
+       function addToDb($filename,$directory_id){
+               global $kfmdb;
+               if(!$directory_id)return $this->error('Directory ID not supplied');
+               $sql="insert into ".KFM_DB_PREFIX."files (name,directory) values('".sql_escape($filename)."',".$directory_id.")";
+               $q=$kfmdb->query($sql);
+               return $kfmdb->lastInsertId(KFM_DB_PREFIX.'files','id');
+       }
+
+       /**
+        * Check if the filename is authorized by the system according to the configuration
+        * @return bool $authorized true when authorized, false if not
+        */
+       function checkName($filename=false){
+               if($filename===false)$filename=$this->name;
+
+               if( 
+                       $filename=='' ||
+                       preg_match('#/|\.$#',$filename) 
+               )return false;
+
+               $exts=explode('.',$filename); 
+               for($i=1;$i<count($exts);++$i){ 
+                       $ext=$exts[$i];
+                       if(in_array($ext,$GLOBALS['kfm_banned_extensions']))return false; 
+               }
+
+               
+               foreach($GLOBALS['kfm_banned_files'] as $ban){
+                       if(($ban[0]=='/' || $ban[0]=='@')&&preg_match($ban,$filename))return false;
+                       elseif($ban==strtolower($filename))return false;
+               }
+
+               if(isset($GLOBALS['kfm_allowed_files']) && is_array($GLOBALS['kfm_allowed_files'])){
+                       foreach($GLOBALS['kfm_allowed_files'] as $allow){
+                               if($allow[0]=='/' || $allow[0]=='@'){
+                                       if(preg_match($allow, $file))return true;
+                               }else if($allow==strtolower($file)) return true;
+                       }
+                       return false;
+               }
+               return true;
+       }
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/files.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/files.php
new file mode 100644 (file)
index 0000000..64921d1
--- /dev/null
@@ -0,0 +1,297 @@
+<?php
+function _copyFiles($files,$dir_id){
+       $copied=0;
+       $dir=kfmDirectory::getInstance($dir_id);
+       foreach($files as $fid){
+               $file=kfmFile::getInstance($fid);
+               if(!$file)continue;
+               if($dir->addFile($file))$copied++;
+       }
+       kfm_addMessage(kfm_lang('filesCopied',$copied));
+}
+function _createEmptyFile($cwd,$filename){
+       global $kfm_session,$kfm_default_upload_permission;
+       $dir=kfmDirectory::getInstance($cwd);
+       $path=$dir->path;
+       if(!kfmFile::checkName($filename))return kfm_error(kfm_lang('illegalFileName',$filename));
+       $success=touch($path.$filename);
+       if($success){
+               chmod($path.$filename, octdec('0'.$kfm_default_upload_permission));
+               return kfm_loadFiles($cwd);
+       }
+       return kfm_error(kfm_lang('couldNotCreateFile',$filename));
+}
+function _downloadFileFromUrl($url,$filename){
+       global $kfm_session,$kfm_default_upload_permission;
+       $cwd_id=$kfm_session->get('cwd_id');
+       $dir=kfmDirectory::getInstance($cwd_id);
+       $cwd=$dir->getPath();
+       if(!kfmFile::checkName($filename))return kfm_error(kfm_lang('error: filename not allowed'));
+       if(substr($url,0,4)!='http')return kfm_error(kfm_lang('error: url must begin with http'));
+       $file=file_get_contents(str_replace(' ','%20',$url));
+       if(!$file)return kfm_lang('failedDownloadFromUrl');
+       if(!file_put_contents($cwd.'/'.$filename,$file))return kfm_lang('failedWriteToFile',$filename);
+       chmod($cwd.'/'.$filename, octdec('0'.$kfm_default_upload_permission));
+       return kfm_loadFiles($cwd_id);
+}
+function _extractZippedFile($id){
+       global $kfm_session;
+       $cwd_id=$kfm_session->get('cwd_id');
+       if(!$GLOBALS['kfm_allow_file_create'])return kfm_error(kfm_lang('permissionDeniedCreateFile'));
+       $file=kfmFile::getInstance($id);
+       $dir=$file->directory.'/';
+       { # try native system unzip command
+               $res=-1;
+               $arr=array();
+               exec('unzip -l "'.$dir.$file->name.'"',$arr,$res);
+               if(!$res){
+                       for($i=3;$i<count($arr)-2;++$i){
+                               $filename=preg_replace('/.* /','',$arr[$i]);
+                               if(!kfmFile::checkName($filename))return kfm_error(kfm_lang('errorZipContainsBannedFilename'));
+                       }
+                       exec('unzip -o "'.$dir.$file->name.'" -x -d "'.$dir.'"',$arr,$res);
+               }
+       }
+       if($res){ # try PHP unzip command
+               return kfm_error(kfm_lang('error: unzip failed'));
+               # TODO: fix this
+               $zip=zip_open($dir.$file->name);
+               while($zip_entry=zip_read($zip)){
+                       $entry=zip_entry_open($zip,$zip_entry);
+                       $filename=zip_entry_name($zip_entry);
+                       $target_dir=$dir.substr($filename,0,strrpos($filename,'/'));
+                       $filesize=zip_entry_filesize($zip_entry);
+                       if(is_dir($target_dir)||mkdir($target_dir)){
+                               if($filesize>0){
+                                       $contents=zip_entry_read($zip_entry,$filesize);
+                                       file_put_contents($dir.$filename,$contents);
+                               }
+                       }
+               }
+       }
+       return kfm_loadFiles($cwd_id);
+}
+function _getFileAsArray($filename){
+       return explode("\n",rtrim(file_get_contents($filename)));
+}
+function _getFileDetails($fid){
+       $file=kfmFile::getInstance($fid);
+       if(!is_object($file))return kfm_lang('failedGetFileObject');
+       $fpath=$file->path;
+       if(!file_exists($fpath))return;
+       $details=array(
+               'id'=>$file->id,
+               'name'=>$file->name,
+               'filename'=>$file->name,
+               'mimetype'=>$file->mimetype,
+               'filesize'=>$file->size2str(),
+               'filesize_raw'=>$file->getSize(),
+               'tags'=>$file->getTags(),
+               'ctime'=>$file->ctime,
+               'modified'=>$file->modified,
+               'writable'=>$file->isWritable(),
+               'ext'=>$file->getExtension()
+       );
+       if($file->isImage()){
+               $details['caption']=$file->caption;
+               $details['width']=$file->width;
+               $details['height']=$file->height;
+               $details['thumb_url']=$file->thumb_url;
+       }
+       return $details;
+}
+function _getFileUrl($fid,$x=0,$y=0){
+       $file=kfmFile::getInstance($fid);
+       return $file->getUrl($x,$y);
+}
+function _getFileUrls($fArr){
+       $rArr=array();
+       foreach($fArr as $f)$rArr[]=_getFileUrl($f);
+       return $rArr;
+}
+function _getTagName($id){
+       global $kfmdb;
+       $r=db_fetch_row("select name from ".KFM_DB_PREFIX."tags where id=".$id);
+       if(count($r))return array($id,$r['name']);
+       return array($id,kfm_lang('UNKNOWN TAG',$id));
+}
+function _getTextFile($fid){
+       $file=kfmFile::getInstance($fid);
+       return array('content'=>$file->getContent(),'name'=>$file->name,'id'=>$file->id);
+}
+function _loadFiles($rootid=1,$setParent=false){
+       global $kfm_session;
+       if(!$rootid)$rootid=1;
+       $dir=kfmDirectory::getInstance($rootid);
+       $oFiles=$dir->getFiles();
+       if($dir->hasErrors())return $dir->getErrors();
+       $files=array();
+       foreach($oFiles as $file)$files[]=_getFileDetails($file);
+       $root='/'.str_replace($GLOBALS['rootdir'],'',$dir->path);
+       $kfm_session->set('cwd_id',$rootid);
+       $ret=array('reqdir'=>$root,'files'=>$files,'uploads_allowed'=>$GLOBALS['kfm_allow_file_upload']); 
+       if($setParent)$ret['parent']=$rootid;
+       return $ret;
+}
+function _moveFiles($files,$dir_id){
+       global $kfmdb,$kfm_session;
+       $cwd_id=$kfm_session->get('cwd_id');
+       foreach($files as $fid){
+               $file=kfmFile::getInstance($fid);
+               if(!$file)continue;
+               $file->move($dir_id);
+       }
+       return kfm_loadFiles($cwd_id);
+}
+function _renameFile($fid,$newfilename,$refreshFiles=true){
+       global $kfm_session;
+       $file=kfmFile::getInstance($fid);
+       $file->rename($newfilename);
+       if($refreshFiles)return kfm_loadFiles($kfm_session->get('cwd_id'));
+}
+function _renameFiles($files,$template){
+       global $kfm_session;
+       $cwd_id=$kfm_session->get('cwd_id');
+       if(!$GLOBALS['kfm_allow_file_edit'])return kfm_error(kfm_lang('permissionDeniedEditFile'));
+       $prefix=preg_replace('/\*.*/','',$template);
+       $postfix=preg_replace('/.*\*/','',$template);
+       $precision=strlen(preg_replace('/[^*]/','',$template));
+       for($i=1;$i<count($files)+1;++$i){
+               $num=str_pad($i,$precision,'0',STR_PAD_LEFT);
+               $ret=_renameFile($files[$i-1],$prefix.$num.$postfix,false);
+               if($ret)return $ret; # error detected
+       }
+       return kfm_loadFiles($cwd_id);
+}
+function _resize_bytes($size){
+       $count=0;
+       $format=array("B","KB","MB","GB","TB","PB","EB","ZB","YB");
+       while(($size/1024)>1&&$count<8){
+               $size=$size/1024;
+               ++$count;
+       }
+       $return=number_format($size,0,'','.')." ".$format[$count];
+       return $return;
+}
+function _rm($id){
+       if(is_array($id)){
+               $counter=0;
+               foreach($id as $fid){
+                       $file=kfmFile::getInstance($fid);
+                       if($file->delete())$counter++;
+               }
+               if($counter>1)kfm_addMessage(kfm_lang('files deleted',$counter));
+       }
+       else{
+               $file=kfmFile::getInstance($id);
+               $file->delete();
+       }
+       return $id;
+}
+function _saveTextFile($fid,$text){
+       if(!$GLOBALS['kfm_allow_file_edit'])return kfm_error(kfm_lang('permissionDeniedEditFile'));
+       $f=kfmFile::getInstance($fid);
+       if(!$f->checkName())return kfm_error(kfm_lang('permissionDeniedEditFile'));
+       if($f->setContent($text))kfm_addMessage(kfm_lang('file saved'));
+}
+function _search($keywords,$tags){
+       global $kfmdb;
+       $files=array();
+       $valid_files=array();
+       if($tags){
+               $arr=explode(',',$tags);
+               foreach($arr as $tag){
+                       $tag=ltrim(rtrim($tag));
+                       if($tag){
+                               $r=db_fetch_row("select id from ".KFM_DB_PREFIX."tags where name='".sql_escape($tag)."'");
+                               if(count($r)){
+                                       $constraints='';
+                                       if(count($valid_files))$constraints=' and (file_id='.join(' or file_id=',$valid_files).')';
+                                       $rs2=db_fetch_all("select file_id from ".KFM_DB_PREFIX."tagged_files where tag_id=".$r['id'].$constraints);
+                                       if(count($rs2)){
+                                               $valid_files=array();
+                                               foreach($rs2 as $r2)$valid_files[]=$r2['file_id'];
+                                       }
+                                       else $valid_files=array(0);
+                               }
+                       }
+               }
+       }
+       if(($tags&&count($valid_files))||$keywords){ # keywords
+               $constraints='';
+               if(count($valid_files))$constraints=' and (id='.join(' or id=',$valid_files).')';
+               $fs=db_fetch_all("select id from ".KFM_DB_PREFIX."files where name like '%".sql_escape($keywords)."%'".$constraints." order by name");
+               foreach($fs as $f){
+                       $file=kfmFile::getInstance($f['id']);
+                       if(!$file->checkName())continue;
+                       unset($file->db);
+                       $files[]=_getFileDetails($f['id']);
+               }
+       }
+       return array('reqdir'=>kfm_lang('searchResults'),'files'=>$files,'uploads_allowed'=>0);
+}
+function _tagAdd($recipients,$tagList){
+       if(!$GLOBALS['kfm_allow_file_edit'])return kfm_error(kfm_lang('permissionDeniedEditFile'));
+       global $kfmdb;
+       if(!is_array($recipients))$recipients=array($recipients);
+       $arr=explode(',',$tagList);
+       $tagList=array();
+       foreach($arr as $v){
+               $v=ltrim(rtrim($v));
+               if($v)$tagList[]=$v;
+       }
+       if(count($tagList))foreach($tagList as $tag){
+               $r=db_fetch_row("select id from ".KFM_DB_PREFIX."tags where name='".sql_escape($tag)."'");
+               if(count($r)){
+                       $tag_id=$r['id'];
+                       $kfmdb->query("delete from ".KFM_DB_PREFIX."tagged_files where tag_id=".$tag_id." and (file_id=".join(' or file_id=',$recipients).")");
+               }
+               else{
+                       $q=$kfmdb->query("insert into ".KFM_DB_PREFIX."tags (name) values('".sql_escape($tag)."')");
+                       $tag_id=$kfmdb->lastInsertId(KFM_DB_PREFIX.'tags','id');
+               }
+               foreach($recipients as $file_id)$kfmdb->query("insert into ".KFM_DB_PREFIX."tagged_files (tag_id,file_id) values(".$tag_id.",".$file_id.")");
+       }
+       return _getFileDetails($recipients[0]);
+}
+function _tagRemove($recipients,$tagList){
+       if(!$GLOBALS['kfm_allow_file_edit'])return kfm_error(kfm_lang('permissionDeniedEditFile'));
+       global $kfmdb;
+       if(!is_array($recipients))$recipients=array($recipients);
+       $arr=explode(',',$tagList);
+       $tagList=array();
+       foreach($arr as $tag){
+               $tag=ltrim(rtrim($tag));
+               if($tag){
+                       $r=db_fetch_row("select id from ".KFM_DB_PREFIX."tags where name='".sql_escape($tag)."'");
+                       if(count($r))$tagList[]=$r['id'];
+               }
+       }
+       if(count($tagList))$kfmdb->exec("delete from ".KFM_DB_PREFIX."tagged_files where (file_id=".join(' or file_id=',$recipients).") and (tag_id=".join(' or tag_id="',$tagList).")");
+       return _getFileDetails($recipients[0]);
+}
+function _zip($filename,$files){
+       global $kfm_session;
+       $cwd_id=$kfm_session->get('cwd_id');
+       $dir=kfmDirectory::getInstance($cwd_id);
+       $cwd=$dir->path;
+       if(!$GLOBALS['kfm_allow_file_create'])return kfm_error(kfm_lang('permissionDeniedCreateFile'));
+       global $rootdir;
+       if(!kfmFile::checkName($filename))return kfm_error(kfm_lang('illegalFileName',$filename));
+       $arr=array();
+       foreach($files as $f){
+               $file=kfmFile::getInstance($f);
+               if(!$file)return kfm_error(kfm_lang('missingFileInSelection'));
+               $arr[]=$file->path;
+       }
+       { # try native system zip command
+               $res=-1;
+               $pdir=$cwd.'/';
+               $zipfile=$pdir.$filename;
+               for($i=0;$i<count($arr);++$i)$arr[$i]=str_replace($pdir,'',$arr[$i]);
+               exec('cd "'.$cwd.'" && zip -D "'.$zipfile.'" "'.join('" "',$arr).'"',$arr,$res);
+       }
+       if($res)return kfm_error(kfm_lang('noNativeZipCommand'));
+       return kfm_loadFiles($cwd_id);
+}
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/image.class.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/image.class.php
new file mode 100644 (file)
index 0000000..dd4e415
--- /dev/null
@@ -0,0 +1,183 @@
+<?php
+$imageInstances=array();
+class kfmImage extends kfmFile{
+       var $caption='';
+       var $width;
+       var $height;
+       var $thumb_url;
+       var $thumb_id;
+       var $thumb_path;
+       var $info=array(); # info from getimagesize
+       function kfmImage($file){
+               if(is_object($file) && $file->isImage())parent::kfmFile($file->id);
+               else if(is_numeric($file))parent::kfmFile($file);
+               else return false;
+               if(!$this->exists()){
+                       $this->delete();
+                       return false;
+               }
+               $this->image_id=$this->getImageId();
+               if($this->getSize()){
+                       $this->info=getimagesize($this->path);
+                       $this->type=str_replace('image/','',$this->info['mime']);
+                       $this->width=$this->info[0];
+                       $this->height=$this->info[1];
+               }
+               else{
+                       $this->type='null';
+                       $this->width=0;
+                       $this->height=0;
+               }
+       }
+       function createResizedCopy($to,$width,$height){
+               $load='imagecreatefrom'.$this->type;
+               $save='image'.$this->type;
+               if(!function_exists($load)||!function_exists($save))return $this->error('server cannot handle image of type "'.$this->type.'"');
+               $im=$load($this->path);
+               $imresized=imagecreatetruecolor($width,$height);
+               imagealphablending($imresized,false);
+               imagecopyresampled($imresized,$im,0,0,0,0,$width,$height,$this->width,$this->height);
+               imagesavealpha($imresized,true);
+               $save($imresized,$to,($this->type=='jpeg'?100:9));
+               imagedestroy($imresized);
+               imagedestroy($im);
+       }
+       function createThumb($width=64,$height=64,$id=0){
+               global $kfm,$kfm_use_imagemagick;
+               if(!is_dir(WORKPATH.'thumbs'))mkdir(WORKPATH.'thumbs');
+               $ratio=min($width/$this->width,$height/$this->height);
+               $thumb_width=$this->width*$ratio;
+               $thumb_height=$this->height*$ratio;
+               if(!$id){
+                       $kfm->db->exec("INSERT INTO ".KFM_DB_PREFIX."files_images_thumbs (image_id,width,height) VALUES(".$this->id.",".$thumb_width.",".$thumb_height.")");
+                       $id=$kfm->db->lastInsertId(KFM_DB_PREFIX.'files_images_thumbs','id');
+               }
+               $file=WORKPATH.'thumbs/'.$id;
+               if(!$kfm_use_imagemagick || $this->useImageMagick($this->path,'resize '.$thumb_width.'x'.$thumb_height,$file))$this->createResizedCopy($file,$thumb_width,$thumb_height);
+               return $id;
+       }
+       function delete(){
+               global $kfm;
+               if(!$GLOBALS['kfm_allow_file_delete'])return $this->error(kfm_lang('permissionDeniedDeleteFile'));
+               if(!parent::delete())return false;
+               $this->deleteThumbs();
+               $kfm->db->exec('DELETE FROM '.KFM_DB_PREFIX.'files_images WHERE file_id='.$this->id);
+               return !$this->hasErrors();
+       }
+       function deleteThumbs(){
+               global $kfm;
+               $rs=db_fetch_all("SELECT id FROM ".KFM_DB_PREFIX."files_images_thumbs WHERE image_id=".$this->id);
+               foreach($rs as $r){
+                       $icons=glob(WORKPATH.'thumbs/'.$r['id'].'*');
+                       foreach($icons as $f)unlink($f);
+               }
+               $kfm->db->exec("DELETE FROM ".KFM_DB_PREFIX."files_images_thumbs WHERE image_id=".$this->id);
+       }
+       function getImageId(){
+               global $kfm;
+               $row=db_fetch_row("SELECT id,caption FROM ".KFM_DB_PREFIX."files_images WHERE file_id='".$this->id."'");
+               if(!$row){ # db record not found. create it
+                       # TODO: retrieve caption generation code from get.php
+                       $sql="INSERT INTO ".KFM_DB_PREFIX."files_images (file_id, caption) VALUES ('".$this->id."','".$this->name."')";
+                       $this->caption=$this->name;
+                       $kfm->db->exec($sql);
+                       return $kfm->db->lastInsertId(KFM_DB_PREFIX.'files_images','id');
+               }
+               $this->caption=$row['caption'];
+               return $row['id'];
+       }
+       function getInstance($id=0){
+               if(!$id)return false;
+               global $imageInstances;
+               if(is_object($id)){
+                       if($id->isImage())$id=$id->id;
+                       else return false;
+               }
+               if(!isset($imageInstances[$id]))$imageInstances[$id]=new kfmImage($id);
+               return $imageInstances[$id];
+       }
+       function resize($new_width, $new_height=-1){
+               global $kfm_use_imagemagick,$kfm_allow_image_manipulation;
+               if(!$kfm_allow_image_manipulation)$this->error(kfm_lang('permissionDeniedManipImage'));
+               if(!$this->isWritable())$this->error(kfm_lang('imageNotWritable'));
+               if($this->hasErrors())return false;
+               $this->deleteThumbs();
+               if($new_height==-1)$new_height=$this->height*$new_width/$this->width;
+               if($kfm_use_imagemagick && !$this->useImageMagick($this->path,'resize '.$new_width.'x'.$new_height,$this->path))return;
+               $this->createResizedCopy($this->path,$new_width,$new_height);
+       }
+       function rotate($direction){
+               global $kfm_use_imagemagick,$kfm_allow_image_manipulation;
+               if(!$kfm_allow_image_manipulation)$this->error(kfm_lang('permissionDeniedManipImage'));
+               if(!$this->isWritable())$this->error(kfm_lang('imageNotWritable'));
+               if($this->hasErrors())return false;
+               $this->deleteThumbs();
+               if($kfm_use_imagemagick && !$this->useImageMagick($this->path,'rotate -'.$direction,$this->path))return;
+               { # else use GD
+                       $load='imagecreatefrom'.$this->type;
+                       $save='image'.$this->type;
+                       $im=$load($this->path);
+                       $im=imagerotate($im,$direction,0);
+                       $save($im,$this->path,($this->type=='jpeg'?100:9));
+                       imagedestroy($im);
+               }
+       }
+       function crop($x1, $y1, $width, $height, $newname=false){
+               global $kfm_use_imagemagick,$kfm_allow_image_manipulation;
+               if(!$kfm_allow_image_manipulation)return $this->error(kfm_lang('permissionDeniedManipImage'));
+               
+               if(!$newname){
+                       $this->deleteThumbs();
+                       if(!$this->isWritable())return $this->error(kfm_lang('imageNotWritable'));
+               }
+               if($kfm_use_imagemagick && $newname && !$this->useImageMagick($this->path,'crop '.$width.'x'.$height.'+'.$x1.'+'.$y1.' +repage', dirname($this->path).'/'.$newname))return;
+               else if($kfm_use_imagemagick && !$this->useImageMagick($this->path,'crop '.$width.'x'.$height.'+'.$x1.'+'.$y1.' +repage', $this->path))return;
+               { # else use GD
+                       $load='imagecreatefrom'.$this->type;
+                       $save='image'.$this->type;
+                       $im=$load($this->path);
+                       $cropped = imagecreatetruecolor($width, $height);
+                       imagecopyresized($cropped, $im, 0, 0, $x1, $y1, $width, $height, $width, $height);
+                       imagedestroy($im);
+                       if($newname){
+                               $save($cropped, dirname($this->path).'/'.$newname, ($this->type=='jpeg'?100:9));
+                       }else{
+                               $save($cropped,$this->path,($this->type=='jpeg'?100:9));
+                       }
+                       imagedestroy($cropped);
+               }
+       }
+       function setCaption($caption){
+               global $kfm;
+               $kfm->db->exec("UPDATE ".KFM_DB_PREFIX."files_images SET caption='".sql_escape($caption)."' WHERE file_id=".$this->id);
+               $this->caption=$caption;
+       }
+       function setThumbnail($width=64,$height=64){
+               $thumbname=$this->id.' '.$width.'x'.$height.' '.$this->name;
+               if(!isset($this->info['mime'])||!in_array($this->info['mime'],array('image/jpeg','image/gif','image/png')))return false;
+               $r=db_fetch_row("SELECT id FROM ".KFM_DB_PREFIX."files_images_thumbs WHERE image_id=".$this->id." and width<=".$width." and height<=".$height." and (width=".$width." or height=".$height.")");
+               if($r){
+                       $id=$r['id'];
+                       if(!file_exists(WORKPATH.'thumbs/'.$id))$this->createThumb($width,$height,$id); // missing thumb file - recreate it
+               }
+               else{
+                       $id=$this->createThumb($width,$height);
+               }
+               $this->thumb_url='get.php?type=thumb&id='.$id.GET_PARAMS;
+               $this->thumb_id=$id;
+               $this->thumb_path=str_replace('//','/',WORKPATH.'thumbs/'.$id);
+               if(!file_exists($this->thumb_path)){
+                       copy(WORKPATH.'thumbs/'.$id.'.'.preg_replace('/.*\//','',$this->info['mime']),$this->thumb_path);
+                       unlink(WORKPATH.'thumbs/'.$id.'.'.preg_replace('/.*\//','',$this->info['mime']));
+               }
+               if(!file_exists($this->thumb_path))$this->createThumb();
+       }
+       function useImageMagick($from,$action,$to){
+               if(!file_exists(IMAGEMAGICK_PATH))return true;
+               $retval=true;
+               $arr=array();
+               exec(IMAGEMAGICK_PATH.' "'.$from.'" -'.$action.' "'.$to.'"',$arr,$retval);
+               return $retval;
+       }
+}
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/images.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/images.php
new file mode 100644 (file)
index 0000000..ba0bd0e
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+function _changeCaption($fid,$newCaption){
+       global $kfm_session;
+       $cwd_id=$kfm_session->get('cwd_id');
+       $im=kfmImage::getInstance($fid);
+       $im->setCaption($newCaption);
+       return kfm_loadFiles($cwd_id);
+}
+function _getThumbnail($fileid,$width,$height){
+       $im=kfmImage::getInstance($fileid);
+       $im->setThumbnail($width,$height); // Already done in the Image constructor, maybe needed for Thumbnails with different sizes.
+       return array($fileid,array('icon'=>$im->thumb_url,'width'=>$im->width,'height'=>$im->height,'caption'=>$im->caption));
+}
+function _resizeImage($fid,$width,$height){
+       global $kfm_session;
+       $cwd_id=$kfm_session->get('cwd_id');
+       $im=kfmImage::getInstance($fid);
+       $im->resize($width, $height);
+       if($im->hasErrors())return $im->getErrors();
+       return kfm_loadFiles($cwd_id);
+}
+function _resizeImages($fs,$width,$height){
+       foreach($fs as $f)_resizeImage($f,$width,$height);
+}
+function _rotateImage($fid,$direction){
+       $im=kfmImage::getInstance($fid);
+       $im->rotate($direction);
+       if($im->hasErrors())return $im->getErrors();
+       return $fid;
+}
+function _setCaption($fid,$caption){
+       
+}
+function _cropToOriginal($fid, $x1, $y1, $width, $height){
+       $im=kfmImage::getInstance($fid);
+       $im->crop($x1, $y1, $width, $height);
+       if($im->hasErrors())return $im->getErrors();
+       return $fid;
+}
+function _cropToNew($fid, $x1, $y1, $width, $height, $newname){
+       global $kfm_session;
+       $cwd_id=$kfm_session->get('cwd_id');
+       $im=kfmImage::getInstance($fid);
+       $im->crop($x1, $y1, $width, $height, $newname);
+       if($im->hasErrors())return $im->getErrors();
+       return kfm_loadFiles($cwd_id);
+}
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/json.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/json.php
new file mode 100644 (file)
index 0000000..128c81d
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+               function json_encode($obj){
+                       $json=new Services_JSON();
+                       return $json->encode($obj);
+               }
+               function json_decode($js){
+                       $json=new Services_JSON();
+                       return $json->decode($js);
+               }
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/kaejax.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/kaejax.php
new file mode 100644 (file)
index 0000000..3accf6f
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+{ # variables
+       $kfm_kaejax_js_has_been_shown=0;
+       $kfm_kaejax_export_list=array();
+       $kfm_kaejax_is_loaded=1;#strstr($_SERVER['REQUEST_URI'],'kfm_kaejax_is_loaded');
+}      
+function kfm_kaejax_handle_client_request(){
+       if(!isset($_POST['kaejax']))return;
+       $unmangled=kfm_decode_unicode_url(str_replace(array('%2B',"\r","\n","\t"),array('+','\r','\n','\t'),$_POST['kaejax']));
+       $obj=json_decode($unmangled);
+       $fs=$obj->c;
+       $ret=array();
+       $ret['results']=array();
+       foreach($fs as $f)$ret['results'][]=call_user_func_array($f->f,$f->v);
+       $ret['errors']=kfm_getErrors();
+       $ret['messages']=kfm_getMessages();
+       header('Content-type: text/javascript; Charset=utf-8');
+       echo json_encode($ret);
+       exit;
+}
+function kfm_kaejax_get_one_stub($func_name){
+       $a='function x_'.$func_name.'(){kfm_kaejax_do_call("'.$func_name.'",$A(arguments));}function_urls.'.$func_name."='".$_SERVER['PHP_SELF'].GET_PARAMS."';";
+       if(!$GLOBALS['kfm_kaejax_is_loaded'])$a.='kfm_kaejax_is_loaded=1;';
+       $GLOBALS['kfm_kaejax_is_loaded']=1;
+       return $a;
+}
+function kfm_kaejax_export(){
+       global $kfm_kaejax_export_list;
+       $n=func_num_args();
+       for($i=0;$i<$n;$i++)$kfm_kaejax_export_list[]=func_get_arg($i);
+}
+function kfm_kaejax_get_javascript(){
+       $html='';
+       if(!$GLOBALS['kfm_kaejax_js_has_been_shown']&&!$GLOBALS['kfm_kaejax_is_loaded'])$GLOBALS['kfm_kaejax_js_has_been_shown']=1;
+       foreach($GLOBALS['kfm_kaejax_export_list'] as $func)$html.=kfm_kaejax_get_one_stub($func);
+       return $html;
+}
+function kfm_decode_unicode_url($str){
+       # this code taken from here: http://php.net/urldecode
+       $res='';
+       $i=0;
+       $max=strlen($str)-6;
+       while($i<=$max){
+               $character=$str[$i];
+               if($character=='%'&&$str[$i+1]=='u'){
+                       $value=hexdec(substr($str,$i+2,4));
+                       $i+=6;
+                       if($value<0x0080)$character=chr($value);
+                       else if($value<0x0800)$character=chr((($value&0x07c0)>>6)|0xc0).chr(($value&0x3f)|0x80);
+                       else $character=chr((($value&0xf000)>>12)|0xe0).chr((($value&0x0fc0)>>6)|0x80).chr(($value&0x3f)|0x80);
+               }
+               else ++$i;
+               $res.=$character;
+       }
+       return $res.substr($str, $i);
+}
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/kfm.class.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/kfm.class.php
new file mode 100644 (file)
index 0000000..09758f7
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Base kfm class
+ */
+class kfmBase extends kfmObject{
+       var $doctype='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
+       var $settings=array();
+
+       /**
+        * setting function, returns a configuration parameter if one config is given, 
+        * sets a config parameter if two parameters are given
+        * @param $name
+        * @param $value optional
+        * 
+        * @return $value
+        */
+       function setting($name,$value='novaluegiven'){
+               if($value=='novaluegiven'){
+                       if(!isset($this->settings[$name]))return $this->error('Setting '.$name.' does not exists');
+                       return $this->settings[$name];
+               }
+               $this->settings[$name]=$value;
+       }
+
+       function defaultSetting($name, $value){
+               if(!isset($this->settings[$name]))$this->settings[$name]=$value;
+       }
+
+       /**
+        * returns a parameter, returns the default if not present
+        * @param $parameter
+        * @param $default
+        * @return $value || $default if not present
+        */
+       function getParameter($parameter, $default=false){
+
+       }
+
+       /**
+        * sets a parameter
+        * @param $parameter parameter name
+        * @param $value parameter value
+        * @return true on success || false on error
+        */
+       function setParameter($parameter, $value){
+
+       }
+}
+$kfm=new kfmBase();
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/lang.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/lang.php
new file mode 100644 (file)
index 0000000..dbccf8f
--- /dev/null
@@ -0,0 +1,12 @@
+<?php
+function kfm_lang($str,$v1='',$v2='',$v3=''){
+       global $kfm_language,$kfm_langStrings;
+       if(!isset($kfm_langStrings)){
+               include KFM_BASE_PATH.'lang/'.$kfm_language.'.php';
+               $GLOBAL['kfm_langStrings']=$kfm_langStrings;
+       }
+       if(isset($kfm_langStrings[$str]))$str=$kfm_langStrings[$str];
+       $i=1;
+       while(strpos($str,'%'.$i)!==false)$str=str_replace('%'.$i,${'v'.$i++},$str);
+       return utf8_encode($str);
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/login.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/login.php
new file mode 100644 (file)
index 0000000..e9f0aea
--- /dev/null
@@ -0,0 +1,29 @@
+<html>
+       <head>
+               <style type="text/css"><?php
+                       $cssfile='themes/'.$kfm_theme.'/login.css';
+                       $css=file_exists($cssfile)?file_get_contents($cssfile):'';
+                       echo preg_replace('/\s+/',' ',$css);
+               ?></style>
+               <title>KFM - Kae's File Manager - Login</title>
+       </head>
+       <body>
+               <form method="post" action="./">
+                       <table>
+                               <tr>
+                                       <th colspan="2">KFM Login</th>
+                               </tr>
+                               <tr>
+                                       <th>Username</th><td><input name="username" /></td>
+                               </tr>
+                               <tr>
+                                       <th>Password</th><td><input type="password" name="password" /></td>
+                               </tr>
+                               <tr>
+                                       <th colspan="2"><input type="submit" value="Login" /></th>
+                               </tr>
+                       </table>
+               </form>
+               <?php if($err)echo $err; ?>
+       </body>
+</html>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/object.class.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/object.class.php
new file mode 100644 (file)
index 0000000..5c0ad7e
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+function kfm_error($message,$level=3){
+       global $kfm_errors;
+       $kfm_errors[]=array('message'=>$message,'level'=>$level);
+       return false;
+}
+function kfm_isError($level=3){
+       global $kfm_errors;
+       foreach($kfm_errors as $error) if($error->level<=$level)return true;
+       return false;
+}
+function kfm_getErrors($level=3){
+       global $kfm_errors;
+       return $kfm_errors;
+}
+function kfm_addMessage($message){
+       global $kfm_messages;
+       $kfm_messages[]=array('message'=>$message);
+}
+function kfm_getMessages(){
+       global $kfm_messages;
+       return $kfm_messages;
+}
+#TODO move the above functions to a separate functions file.
+class kfmObject{
+       var $error_array = array();
+       function __construct(){
+               $this->kfmObject();
+       }
+       function kfmObject(){
+               //global $kfmdb,$kfm_db_type;
+               //$this->db=&$kfmdb;
+               //$this->db_prefix=KFM_DB_PREFIX;
+               //$this->db_type=&$kfm_db_type;
+       }
+       function error($message, $level=3){
+               global $kfm_errors;
+               $info=array('function'=>'','class'=>'','file'=>'');
+               $trace=debug_backtrace();
+               $previous_level=array_shift($trace);
+               //Select the info of the top level class
+               foreach($trace as $errorlevel){
+                       if(!isset($errorlevel['class'])){
+                               $info=$previous_level;
+                               break;
+                       }
+                       $previous_level=$errorlevel;
+               }
+               $error=array(
+                       'message'=>$message, 
+                       'level'=>$level,
+                       'function'=>$info['function'],
+                       'class'=>$info['class'],
+                       'file'=>$info['file']);
+               $this->error_array[] = $message;
+               $kfm_errors[]=$error;
+               return false;
+       }
+       function hasErrors(){
+               if(count($this->error_array)) return true;
+               return false;
+       }
+       function getErrors(){
+               // short term ugly solution
+               return 'error: '.implode("_", $this->error_array);
+       }
+       function addErrors($object){
+               array_merge_recursive($this->error_array, $object->error_array);
+       }
+       function checkAddr($addr){
+               return (
+                       strpos($addr,'..')===false&&
+                       strpos($addr,'.')!==0&&
+                       strpos($addr,'/.')===false&&
+                       !in_array(preg_replace('/.*\./','',$addr),$GLOBALS['kfm_banned_extensions'])
+               );
+       }
+}
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/JSON.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/JSON.php
new file mode 100644 (file)
index 0000000..0cddbdd
--- /dev/null
@@ -0,0 +1,806 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Converts to and from JSON format.
+ *
+ * JSON (JavaScript Object Notation) is a lightweight data-interchange
+ * format. It is easy for humans to read and write. It is easy for machines
+ * to parse and generate. It is based on a subset of the JavaScript
+ * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
+ * This feature can also be found in  Python. JSON is a text format that is
+ * completely language independent but uses conventions that are familiar
+ * to programmers of the C-family of languages, including C, C++, C#, Java,
+ * JavaScript, Perl, TCL, and many others. These properties make JSON an
+ * ideal data-interchange language.
+ *
+ * This package provides a simple encoder and decoder for JSON notation. It
+ * is intended for use with client-side Javascript applications that make
+ * use of HTTPRequest to perform server communication functions - data can
+ * be encoded into JSON notation for use in a client-side javascript, or
+ * decoded from incoming Javascript requests. JSON format is native to
+ * Javascript, and can be directly eval()'ed with no further parsing
+ * overhead
+ *
+ * All strings should be in ASCII or UTF-8 format!
+ *
+ * LICENSE: 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.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 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.
+ *
+ * @category
+ * @package     Services_JSON
+ * @author      Michal Migurski <mike-json@teczno.com>
+ * @author      Matt Knapp <mdknapp[at]gmail[dot]com>
+ * @author      Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
+ * @copyright   2005 Michal Migurski
+ * @version     CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
+ * @license     http://www.opensource.org/licenses/bsd-license.php
+ * @link        http://pear.php.net/pepr/pepr-proposal-show.php?id=198
+ */
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_SLICE',   1);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_STR',  2);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_ARR',  3);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_OBJ',  4);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_CMT', 5);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_LOOSE_TYPE', 16);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
+
+/**
+ * Converts to and from JSON format.
+ *
+ * Brief example of use:
+ *
+ * <code>
+ * // create a new instance of Services_JSON
+ * $json = new Services_JSON();
+ *
+ * // convert a complexe value to JSON notation, and send it to the browser
+ * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
+ * $output = $json->encode($value);
+ *
+ * print($output);
+ * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
+ *
+ * // accept incoming POST data, assumed to be in JSON notation
+ * $input = file_get_contents('php://input', 1000000);
+ * $value = $json->decode($input);
+ * </code>
+ */
+class Services_JSON
+{
+   /**
+    * constructs a new JSON instance
+    *
+    * @param    int     $use    object behavior flags; combine with boolean-OR
+    *
+    *                           possible values:
+    *                           - SERVICES_JSON_LOOSE_TYPE:  loose typing.
+    *                                   "{...}" syntax creates associative arrays
+    *                                   instead of objects in decode().
+    *                           - SERVICES_JSON_SUPPRESS_ERRORS:  error suppression.
+    *                                   Values which can't be encoded (e.g. resources)
+    *                                   appear as NULL instead of throwing errors.
+    *                                   By default, a deeply-nested resource will
+    *                                   bubble up with an error, so all return values
+    *                                   from encode() should be checked with isError()
+    */
+    function Services_JSON($use = 0)
+    {
+        $this->use = $use;
+    }
+
+   /**
+    * convert a string from one UTF-16 char to one UTF-8 char
+    *
+    * Normally should be handled by mb_convert_encoding, but
+    * provides a slower PHP-only method for installations
+    * that lack the multibye string extension.
+    *
+    * @param    string  $utf16  UTF-16 character
+    * @return   string  UTF-8 character
+    * @access   private
+    */
+    function utf162utf8($utf16)
+    {
+        // oh please oh please oh please oh please oh please
+        if(function_exists('mb_convert_encoding')) {
+            return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
+        }
+
+        $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
+
+        switch(true) {
+            case ((0x7F & $bytes) == $bytes):
+                // this case should never be reached, because we are in ASCII range
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0x7F & $bytes);
+
+            case (0x07FF & $bytes) == $bytes:
+                // return a 2-byte UTF-8 character
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0xC0 | (($bytes >> 6) & 0x1F))
+                     . chr(0x80 | ($bytes & 0x3F));
+
+            case (0xFFFF & $bytes) == $bytes:
+                // return a 3-byte UTF-8 character
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0xE0 | (($bytes >> 12) & 0x0F))
+                     . chr(0x80 | (($bytes >> 6) & 0x3F))
+                     . chr(0x80 | ($bytes & 0x3F));
+        }
+
+        // ignoring UTF-32 for now, sorry
+        return '';
+    }
+
+   /**
+    * convert a string from one UTF-8 char to one UTF-16 char
+    *
+    * Normally should be handled by mb_convert_encoding, but
+    * provides a slower PHP-only method for installations
+    * that lack the multibye string extension.
+    *
+    * @param    string  $utf8   UTF-8 character
+    * @return   string  UTF-16 character
+    * @access   private
+    */
+    function utf82utf16($utf8)
+    {
+        // oh please oh please oh please oh please oh please
+        if(function_exists('mb_convert_encoding')) {
+            return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
+        }
+
+        switch(strlen($utf8)) {
+            case 1:
+                // this case should never be reached, because we are in ASCII range
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return $utf8;
+
+            case 2:
+                // return a UTF-16 character from a 2-byte UTF-8 char
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0x07 & (ord($utf8{0}) >> 2))
+                     . chr((0xC0 & (ord($utf8{0}) << 6))
+                         | (0x3F & ord($utf8{1})));
+
+            case 3:
+                // return a UTF-16 character from a 3-byte UTF-8 char
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr((0xF0 & (ord($utf8{0}) << 4))
+                         | (0x0F & (ord($utf8{1}) >> 2)))
+                     . chr((0xC0 & (ord($utf8{1}) << 6))
+                         | (0x7F & ord($utf8{2})));
+        }
+
+        // ignoring UTF-32 for now, sorry
+        return '';
+    }
+
+   /**
+    * encodes an arbitrary variable into JSON format
+    *
+    * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
+    *                           see argument 1 to Services_JSON() above for array-parsing behavior.
+    *                           if var is a strng, note that encode() always expects it
+    *                           to be in ASCII or UTF-8 format!
+    *
+    * @return   mixed   JSON string representation of input var or an error if a problem occurs
+    * @access   public
+    */
+    function encode($var)
+    {
+        switch (gettype($var)) {
+            case 'boolean':
+                return $var ? 'true' : 'false';
+
+            case 'NULL':
+                return 'null';
+
+            case 'integer':
+                return (int) $var;
+
+            case 'double':
+            case 'float':
+                return (float) $var;
+
+            case 'string':
+                // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
+                $ascii = '';
+                $strlen_var = strlen($var);
+
+               /*
+                * Iterate over every character in the string,
+                * escaping with a slash or encoding to UTF-8 where necessary
+                */
+                for ($c = 0; $c < $strlen_var; ++$c) {
+
+                    $ord_var_c = ord($var{$c});
+
+                    switch (true) {
+                        case $ord_var_c == 0x08:
+                            $ascii .= '\b';
+                            break;
+                        case $ord_var_c == 0x09:
+                            $ascii .= '\t';
+                            break;
+                        case $ord_var_c == 0x0A:
+                            $ascii .= '\n';
+                            break;
+                        case $ord_var_c == 0x0C:
+                            $ascii .= '\f';
+                            break;
+                        case $ord_var_c == 0x0D:
+                            $ascii .= '\r';
+                            break;
+
+                        case $ord_var_c == 0x22:
+                        case $ord_var_c == 0x2F:
+                        case $ord_var_c == 0x5C:
+                            // double quote, slash, slosh
+                            $ascii .= '\\'.$var{$c};
+                            break;
+
+                        case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
+                            // characters U-00000000 - U-0000007F (same as ASCII)
+                            $ascii .= $var{$c};
+                            break;
+
+                        case (($ord_var_c & 0xE0) == 0xC0):
+                            // characters U-00000080 - U-000007FF, mask 110XXXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
+                            $c += 1;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+
+                        case (($ord_var_c & 0xF0) == 0xE0):
+                            // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}));
+                            $c += 2;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+
+                        case (($ord_var_c & 0xF8) == 0xF0):
+                            // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}));
+                            $c += 3;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+
+                        case (($ord_var_c & 0xFC) == 0xF8):
+                            // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}));
+                            $c += 4;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+
+                        case (($ord_var_c & 0xFE) == 0xFC):
+                            // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}),
+                                         ord($var{$c + 5}));
+                            $c += 5;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+                    }
+                }
+
+                return '"'.$ascii.'"';
+
+            case 'array':
+               /*
+                * As per JSON spec if any array key is not an integer
+                * we must treat the the whole array as an object. We
+                * also try to catch a sparsely populated associative
+                * array with numeric keys here because some JS engines
+                * will create an array with empty indexes up to
+                * max_index which can cause memory issues and because
+                * the keys, which may be relevant, will be remapped
+                * otherwise.
+                *
+                * As per the ECMA and JSON specification an object may
+                * have any string as a property. Unfortunately due to
+                * a hole in the ECMA specification if the key is a
+                * ECMA reserved word or starts with a digit the
+                * parameter is only accessible using ECMAScript's
+                * bracket notation.
+                */
+
+                // treat as a JSON object
+                if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
+                    $properties = array_map(array($this, 'name_value'),
+                                            array_keys($var),
+                                            array_values($var));
+
+                    foreach($properties as $property) {
+                        if(Services_JSON::isError($property)) {
+                            return $property;
+                        }
+                    }
+
+                    return '{' . join(',', $properties) . '}';
+                }
+
+                // treat it like a regular array
+                $elements = array_map(array($this, 'encode'), $var);
+
+                foreach($elements as $element) {
+                    if(Services_JSON::isError($element)) {
+                        return $element;
+                    }
+                }
+
+                return '[' . join(',', $elements) . ']';
+
+            case 'object':
+                $vars = get_object_vars($var);
+
+                $properties = array_map(array($this, 'name_value'),
+                                        array_keys($vars),
+                                        array_values($vars));
+
+                foreach($properties as $property) {
+                    if(Services_JSON::isError($property)) {
+                        return $property;
+                    }
+                }
+
+                return '{' . join(',', $properties) . '}';
+
+            default:
+                return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
+                    ? 'null'
+                    : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
+        }
+    }
+
+   /**
+    * array-walking function for use in generating JSON-formatted name-value pairs
+    *
+    * @param    string  $name   name of key to use
+    * @param    mixed   $value  reference to an array element to be encoded
+    *
+    * @return   string  JSON-formatted name-value pair, like '"name":value'
+    * @access   private
+    */
+    function name_value($name, $value)
+    {
+        $encoded_value = $this->encode($value);
+
+        if(Services_JSON::isError($encoded_value)) {
+            return $encoded_value;
+        }
+
+        return $this->encode(strval($name)) . ':' . $encoded_value;
+    }
+
+   /**
+    * reduce a string by removing leading and trailing comments and whitespace
+    *
+    * @param    $str    string      string value to strip of comments and whitespace
+    *
+    * @return   string  string value stripped of comments and whitespace
+    * @access   private
+    */
+    function reduce_string($str)
+    {
+        $str = preg_replace(array(
+
+                // eliminate single line comments in '// ...' form
+                '#^\s*//(.+)$#m',
+
+                // eliminate multi-line comments in '/* ... */' form, at start of string
+                '#^\s*/\*(.+)\*/#Us',
+
+                // eliminate multi-line comments in '/* ... */' form, at end of string
+                '#/\*(.+)\*/\s*$#Us'
+
+            ), '', $str);
+
+        // eliminate extraneous space
+        return trim($str);
+    }
+
+   /**
+    * decodes a JSON string into appropriate variable
+    *
+    * @param    string  $str    JSON-formatted string
+    *
+    * @return   mixed   number, boolean, string, array, or object
+    *                   corresponding to given JSON input string.
+    *                   See argument 1 to Services_JSON() above for object-output behavior.
+    *                   Note that decode() always returns strings
+    *                   in ASCII or UTF-8 format!
+    * @access   public
+    */
+    function decode($str)
+    {
+        $str = $this->reduce_string($str);
+
+        switch (strtolower($str)) {
+            case 'true':
+                return true;
+
+            case 'false':
+                return false;
+
+            case 'null':
+                return null;
+
+            default:
+                $m = array();
+
+                if (is_numeric($str)) {
+                    // Lookie-loo, it's a number
+
+                    // This would work on its own, but I'm trying to be
+                    // good about returning integers where appropriate:
+                    // return (float)$str;
+
+                    // Return float or int, as appropriate
+                    return ((float)$str == (integer)$str)
+                        ? (integer)$str
+                        : (float)$str;
+
+                } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
+                    // STRINGS RETURNED IN UTF-8 FORMAT
+                    $delim = substr($str, 0, 1);
+                    $chrs = substr($str, 1, -1);
+                    $utf8 = '';
+                    $strlen_chrs = strlen($chrs);
+
+                    for ($c = 0; $c < $strlen_chrs; ++$c) {
+
+                        $substr_chrs_c_2 = substr($chrs, $c, 2);
+                        $ord_chrs_c = ord($chrs{$c});
+
+                        switch (true) {
+                            case $substr_chrs_c_2 == '\b':
+                                $utf8 .= chr(0x08);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\t':
+                                $utf8 .= chr(0x09);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\n':
+                                $utf8 .= chr(0x0A);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\f':
+                                $utf8 .= chr(0x0C);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\r':
+                                $utf8 .= chr(0x0D);
+                                ++$c;
+                                break;
+
+                            case $substr_chrs_c_2 == '\\"':
+                            case $substr_chrs_c_2 == '\\\'':
+                            case $substr_chrs_c_2 == '\\\\':
+                            case $substr_chrs_c_2 == '\\/':
+                                if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
+                                   ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
+                                    $utf8 .= $chrs{++$c};
+                                }
+                                break;
+
+                            case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
+                                // single, escaped unicode character
+                                $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
+                                       . chr(hexdec(substr($chrs, ($c + 4), 2)));
+                                $utf8 .= $this->utf162utf8($utf16);
+                                $c += 5;
+                                break;
+
+                            case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
+                                $utf8 .= $chrs{$c};
+                                break;
+
+                            case ($ord_chrs_c & 0xE0) == 0xC0:
+                                // characters U-00000080 - U-000007FF, mask 110XXXXX
+                                //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 2);
+                                ++$c;
+                                break;
+
+                            case ($ord_chrs_c & 0xF0) == 0xE0:
+                                // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 3);
+                                $c += 2;
+                                break;
+
+                            case ($ord_chrs_c & 0xF8) == 0xF0:
+                                // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 4);
+                                $c += 3;
+                                break;
+
+                            case ($ord_chrs_c & 0xFC) == 0xF8:
+                                // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 5);
+                                $c += 4;
+                                break;
+
+                            case ($ord_chrs_c & 0xFE) == 0xFC:
+                                // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 6);
+                                $c += 5;
+                                break;
+
+                        }
+
+                    }
+
+                    return $utf8;
+
+                } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
+                    // array, or object notation
+
+                    if ($str{0} == '[') {
+                        $stk = array(SERVICES_JSON_IN_ARR);
+                        $arr = array();
+                    } else {
+                        if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
+                            $stk = array(SERVICES_JSON_IN_OBJ);
+                            $obj = array();
+                        } else {
+                            $stk = array(SERVICES_JSON_IN_OBJ);
+                            $obj = new stdClass();
+                        }
+                    }
+
+                    array_push($stk, array('what'  => SERVICES_JSON_SLICE,
+                                           'where' => 0,
+                                           'delim' => false));
+
+                    $chrs = substr($str, 1, -1);
+                    $chrs = $this->reduce_string($chrs);
+
+                    if ($chrs == '') {
+                        if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                            return $arr;
+
+                        } else {
+                            return $obj;
+
+                        }
+                    }
+
+                    //print("\nparsing {$chrs}\n");
+
+                    $strlen_chrs = strlen($chrs);
+
+                    for ($c = 0; $c <= $strlen_chrs; ++$c) {
+
+                        $top = end($stk);
+                        $substr_chrs_c_2 = substr($chrs, $c, 2);
+
+                        if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
+                            // found a comma that is not inside a string, array, etc.,
+                            // OR we've reached the end of the character list
+                            $slice = substr($chrs, $top['where'], ($c - $top['where']));
+                            array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
+                            //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                            if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                                // we are in an array, so just push an element onto the stack
+                                array_push($arr, $this->decode($slice));
+
+                            } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+                                // we are in an object, so figure
+                                // out the property name and set an
+                                // element in an associative array,
+                                // for now
+                                $parts = array();
+                                
+                                if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+                                    // "name":value pair
+                                    $key = $this->decode($parts[1]);
+                                    $val = $this->decode($parts[2]);
+
+                                    if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
+                                        $obj[$key] = $val;
+                                    } else {
+                                        $obj->$key = $val;
+                                    }
+                                } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+                                    // name:value pair, where name is unquoted
+                                    $key = $parts[1];
+                                    $val = $this->decode($parts[2]);
+
+                                    if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
+                                        $obj[$key] = $val;
+                                    } else {
+                                        $obj->$key = $val;
+                                    }
+                                }
+
+                            }
+
+                        } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
+                            // found a quote, and we are not inside a string
+                            array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
+                            //print("Found start of string at {$c}\n");
+
+                        } elseif (($chrs{$c} == $top['delim']) &&
+                                 ($top['what'] == SERVICES_JSON_IN_STR) &&
+                                 ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
+                            // found a quote, we're in a string, and it's not escaped
+                            // we know that it's not escaped becase there is _not_ an
+                            // odd number of backslashes at the end of the string so far
+                            array_pop($stk);
+                            //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
+
+                        } elseif (($chrs{$c} == '[') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a left-bracket, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
+                            //print("Found start of array at {$c}\n");
+
+                        } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
+                            // found a right-bracket, and we're in an array
+                            array_pop($stk);
+                            //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        } elseif (($chrs{$c} == '{') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a left-brace, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
+                            //print("Found start of object at {$c}\n");
+
+                        } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
+                            // found a right-brace, and we're in an object
+                            array_pop($stk);
+                            //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        } elseif (($substr_chrs_c_2 == '/*') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a comment start, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
+                            $c++;
+                            //print("Found start of comment at {$c}\n");
+
+                        } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
+                            // found a comment end, and we're in one now
+                            array_pop($stk);
+                            $c++;
+
+                            for ($i = $top['where']; $i <= $c; ++$i)
+                                $chrs = substr_replace($chrs, ' ', $i, 1);
+
+                            //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        }
+
+                    }
+
+                    if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                        return $arr;
+
+                    } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+                        return $obj;
+
+                    }
+
+                }
+        }
+    }
+
+    /**
+     * @todo Ultimately, this should just call PEAR::isError()
+     */
+    function isError($data, $code = null)
+    {
+        if (class_exists('pear')) {
+            return PEAR::isError($data, $code);
+        } elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
+                                 is_subclass_of($data, 'services_json_error'))) {
+            return true;
+        }
+
+        return false;
+    }
+}
+
+if (class_exists('PEAR_Error')) {
+
+    class Services_JSON_Error extends PEAR_Error
+    {
+        function Services_JSON_Error($message = 'unknown error', $code = null,
+                                     $mode = null, $options = null, $userinfo = null)
+        {
+            parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
+        }
+    }
+
+} else {
+
+    /**
+     * @todo Ultimately, this class shall be descended from PEAR_Error
+     */
+    class Services_JSON_Error
+    {
+        function Services_JSON_Error($message = 'unknown error', $code = null,
+                                     $mode = null, $options = null, $userinfo = null)
+        {
+
+        }
+    }
+
+}
+    
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2.php
new file mode 100644 (file)
index 0000000..e0ca3d8
--- /dev/null
@@ -0,0 +1,4271 @@
+<?php
+// vim: set et ts=4 sw=4 fdm=marker:
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: MDB2.php,v 1.292 2007/04/25 09:31:01 quipo Exp $
+//
+
+/**
+ * @package     MDB2
+ * @category    Database
+ * @author      Lukas Smith <smith@pooteeweet.org>
+ */
+
+require_once 'PEAR.php';
+
+// {{{ Error constants
+
+/**
+ * The method mapErrorCode in each MDB2_dbtype implementation maps
+ * native error codes to one of these.
+ *
+ * If you add an error code here, make sure you also add a textual
+ * version of it in MDB2::errorMessage().
+ */
+
+define('MDB2_OK',                      true);
+define('MDB2_ERROR',                     -1);
+define('MDB2_ERROR_SYNTAX',              -2);
+define('MDB2_ERROR_CONSTRAINT',          -3);
+define('MDB2_ERROR_NOT_FOUND',           -4);
+define('MDB2_ERROR_ALREADY_EXISTS',      -5);
+define('MDB2_ERROR_UNSUPPORTED',         -6);
+define('MDB2_ERROR_MISMATCH',            -7);
+define('MDB2_ERROR_INVALID',             -8);
+define('MDB2_ERROR_NOT_CAPABLE',         -9);
+define('MDB2_ERROR_TRUNCATED',          -10);
+define('MDB2_ERROR_INVALID_NUMBER',     -11);
+define('MDB2_ERROR_INVALID_DATE',       -12);
+define('MDB2_ERROR_DIVZERO',            -13);
+define('MDB2_ERROR_NODBSELECTED',       -14);
+define('MDB2_ERROR_CANNOT_CREATE',      -15);
+define('MDB2_ERROR_CANNOT_DELETE',      -16);
+define('MDB2_ERROR_CANNOT_DROP',        -17);
+define('MDB2_ERROR_NOSUCHTABLE',        -18);
+define('MDB2_ERROR_NOSUCHFIELD',        -19);
+define('MDB2_ERROR_NEED_MORE_DATA',     -20);
+define('MDB2_ERROR_NOT_LOCKED',         -21);
+define('MDB2_ERROR_VALUE_COUNT_ON_ROW', -22);
+define('MDB2_ERROR_INVALID_DSN',        -23);
+define('MDB2_ERROR_CONNECT_FAILED',     -24);
+define('MDB2_ERROR_EXTENSION_NOT_FOUND',-25);
+define('MDB2_ERROR_NOSUCHDB',           -26);
+define('MDB2_ERROR_ACCESS_VIOLATION',   -27);
+define('MDB2_ERROR_CANNOT_REPLACE',     -28);
+define('MDB2_ERROR_CONSTRAINT_NOT_NULL',-29);
+define('MDB2_ERROR_DEADLOCK',           -30);
+define('MDB2_ERROR_CANNOT_ALTER',       -31);
+define('MDB2_ERROR_MANAGER',            -32);
+define('MDB2_ERROR_MANAGER_PARSE',      -33);
+define('MDB2_ERROR_LOADMODULE',         -34);
+define('MDB2_ERROR_INSUFFICIENT_DATA',  -35);
+// }}}
+// {{{ Verbose constants
+/**
+ * These are just helper constants to more verbosely express parameters to prepare()
+ */
+
+define('MDB2_PREPARE_MANIP', false);
+define('MDB2_PREPARE_RESULT', null);
+
+// }}}
+// {{{ Fetchmode constants
+
+/**
+ * This is a special constant that tells MDB2 the user hasn't specified
+ * any particular get mode, so the default should be used.
+ */
+define('MDB2_FETCHMODE_DEFAULT', 0);
+
+/**
+ * Column data indexed by numbers, ordered from 0 and up
+ */
+define('MDB2_FETCHMODE_ORDERED', 1);
+
+/**
+ * Column data indexed by column names
+ */
+define('MDB2_FETCHMODE_ASSOC', 2);
+
+/**
+ * Column data as object properties
+ */
+define('MDB2_FETCHMODE_OBJECT', 3);
+
+/**
+ * For multi-dimensional results: normally the first level of arrays
+ * is the row number, and the second level indexed by column number or name.
+ * MDB2_FETCHMODE_FLIPPED switches this order, so the first level of arrays
+ * is the column name, and the second level the row number.
+ */
+define('MDB2_FETCHMODE_FLIPPED', 4);
+
+// }}}
+// {{{ Portability mode constants
+
+/**
+ * Portability: turn off all portability features.
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_NONE', 0);
+
+/**
+ * Portability: convert names of tables and fields to case defined in the
+ * "field_case" option when using the query*(), fetch*() and tableInfo() methods.
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_FIX_CASE', 1);
+
+/**
+ * Portability: right trim the data output by query*() and fetch*().
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_RTRIM', 2);
+
+/**
+ * Portability: force reporting the number of rows deleted.
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_DELETE_COUNT', 4);
+
+/**
+ * Portability: not needed in MDB2 (just left here for compatibility to DB)
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_NUMROWS', 8);
+
+/**
+ * Portability: makes certain error messages in certain drivers compatible
+ * with those from other DBMS's.
+ *
+ * + mysql, mysqli:  change unique/primary key constraints
+ *   MDB2_ERROR_ALREADY_EXISTS -> MDB2_ERROR_CONSTRAINT
+ *
+ * + odbc(access):  MS's ODBC driver reports 'no such field' as code
+ *   07001, which means 'too few parameters.'  When this option is on
+ *   that code gets mapped to MDB2_ERROR_NOSUCHFIELD.
+ *
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_ERRORS', 16);
+
+/**
+ * Portability: convert empty values to null strings in data output by
+ * query*() and fetch*().
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_EMPTY_TO_NULL', 32);
+
+/**
+ * Portability: removes database/table qualifiers from associative indexes
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES', 64);
+
+/**
+ * Portability: turn on all portability features.
+ * @see MDB2_Driver_Common::setOption()
+ */
+define('MDB2_PORTABILITY_ALL', 127);
+
+// }}}
+// {{{ Globals for class instance tracking
+
+/**
+ * These are global variables that are used to track the various class instances
+ */
+
+$GLOBALS['_MDB2_databases'] = array();
+$GLOBALS['_MDB2_dsninfo_default'] = array(
+    'phptype'  => false,
+    'dbsyntax' => false,
+    'username' => false,
+    'password' => false,
+    'protocol' => false,
+    'hostspec' => false,
+    'port'     => false,
+    'socket'   => false,
+    'database' => false,
+    'mode'     => false,
+);
+
+// }}}
+// {{{ class MDB2
+
+/**
+ * The main 'MDB2' class is simply a container class with some static
+ * methods for creating DB objects as well as some utility functions
+ * common to all parts of DB.
+ *
+ * The object model of MDB2 is as follows (indentation means inheritance):
+ *
+ * MDB2          The main MDB2 class.  This is simply a utility class
+ *              with some 'static' methods for creating MDB2 objects as
+ *              well as common utility functions for other MDB2 classes.
+ *
+ * MDB2_Driver_Common   The base for each MDB2 implementation.  Provides default
+ * |            implementations (in OO lingo virtual methods) for
+ * |            the actual DB implementations as well as a bunch of
+ * |            query utility functions.
+ * |
+ * +-MDB2_Driver_mysql  The MDB2 implementation for MySQL. Inherits MDB2_Driver_Common.
+ *              When calling MDB2::factory or MDB2::connect for MySQL
+ *              connections, the object returned is an instance of this
+ *              class.
+ * +-MDB2_Driver_pgsql  The MDB2 implementation for PostGreSQL. Inherits MDB2_Driver_Common.
+ *              When calling MDB2::factory or MDB2::connect for PostGreSQL
+ *              connections, the object returned is an instance of this
+ *              class.
+ *
+ * @package     MDB2
+ * @category    Database
+ * @author      Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2
+{
+    // {{{ function setOptions(&$db, $options)
+
+    /**
+     * set option array   in an exiting database object
+     *
+     * @param   MDB2_Driver_Common  MDB2 object
+     * @param   array   An associative array of option names and their values.
+     *
+     * @return mixed   MDB2_OK or a PEAR Error object
+     *
+     * @access  public
+     */
+    function setOptions(&$db, $options)
+    {
+        if (is_array($options)) {
+            foreach ($options as $option => $value) {
+                $test = $db->setOption($option, $value);
+                if (PEAR::isError($test)) {
+                    return $test;
+                }
+            }
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function classExists($classname)
+
+    /**
+     * Checks if a class exists without triggering __autoload
+     *
+     * @param   string  classname
+     *
+     * @return  bool    true success and false on error
+     * @static
+     * @access  public
+     */
+    function classExists($classname)
+    {
+        if (version_compare(phpversion(), "5.0", ">=")) {
+            return class_exists($classname, false);
+        }
+        return class_exists($classname);
+    }
+
+    // }}}
+    // {{{ function loadClass($class_name, $debug)
+
+    /**
+     * Loads a PEAR class.
+     *
+     * @param   string  classname to load
+     * @param   bool    if errors should be suppressed
+     *
+     * @return  mixed   true success or PEAR_Error on failure
+     *
+     * @access  public
+     */
+    function loadClass($class_name, $debug)
+    {
+        if (!MDB2::classExists($class_name)) {
+            $file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name).'.php';
+            if ($debug) {
+                $include = include_once($file_name);
+            } else {
+                $include = @include_once($file_name);
+            }
+            if (!$include) {
+                if (!MDB2::fileExists($file_name)) {
+                    $msg = "unable to find package '$class_name' file '$file_name'";
+                } else {
+                    $msg = "unable to load class '$class_name' from file '$file_name'";
+                }
+                $err =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, $msg);
+                return $err;
+            }
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function &factory($dsn, $options = false)
+
+    /**
+     * Create a new MDB2 object for the specified database type
+     *
+     * IMPORTANT: In order for MDB2 to work properly it is necessary that
+     * you make sure that you work with a reference of the original
+     * object instead of a copy (this is a PHP4 quirk).
+     *
+     * For example:
+     *     $db =& MDB2::factory($dsn);
+     *          ^^
+     * And not:
+     *     $db = MDB2::factory($dsn);
+     *
+     * @param   mixed   'data source name', see the MDB2::parseDSN
+     *                      method for a description of the dsn format.
+     *                      Can also be specified as an array of the
+     *                      format returned by MDB2::parseDSN.
+     * @param   array   An associative array of option names and
+     *                            their values.
+     *
+     * @return  mixed   a newly created MDB2 object, or false on error
+     *
+     * @access  public
+     */
+    function &factory($dsn, $options = false)
+    {
+        $dsninfo = MDB2::parseDSN($dsn);
+        if (empty($dsninfo['phptype'])) {
+            $err =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND,
+                null, null, 'no RDBMS driver specified');
+            return $err;
+        }
+        $class_name = 'MDB2_Driver_'.$dsninfo['phptype'];
+
+        $debug = (!empty($options['debug']));
+        $err = MDB2::loadClass($class_name, $debug);
+        if (PEAR::isError($err)) {
+            return $err;
+        }
+
+        $db =& new $class_name();
+        $db->setDSN($dsninfo);
+        $err = MDB2::setOptions($db, $options);
+        if (PEAR::isError($err)) {
+            return $err;
+        }
+
+        return $db;
+    }
+
+    // }}}
+    // {{{ function &connect($dsn, $options = false)
+
+    /**
+     * Create a new MDB2 connection object and connect to the specified
+     * database
+     *
+     * IMPORTANT: In order for MDB2 to work properly it is necessary that
+     * you make sure that you work with a reference of the original
+     * object instead of a copy (this is a PHP4 quirk).
+     *
+     * For example:
+     *     $db =& MDB2::connect($dsn);
+     *          ^^
+     * And not:
+     *     $db = MDB2::connect($dsn);
+     *          ^^
+     *
+     * @param   mixed   'data source name', see the MDB2::parseDSN
+     *                            method for a description of the dsn format.
+     *                            Can also be specified as an array of the
+     *                            format returned by MDB2::parseDSN.
+     * @param   array   An associative array of option names and
+     *                            their values.
+     *
+     * @return  mixed   a newly created MDB2 connection object, or a MDB2
+     *                  error object on error
+     *
+     * @access  public
+     * @see     MDB2::parseDSN
+     */
+    function &connect($dsn, $options = false)
+    {
+        $db =& MDB2::factory($dsn, $options);
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $err = $db->connect();
+        if (PEAR::isError($err)) {
+            $dsn = $db->getDSN('string', 'xxx');
+            $db->disconnect();
+            $err->addUserInfo($dsn);
+            return $err;
+        }
+
+        return $db;
+    }
+
+    // }}}
+    // {{{ function &singleton($dsn = null, $options = false)
+
+    /**
+     * Returns a MDB2 connection with the requested DSN.
+     * A new MDB2 connection object is only created if no object with the
+     * requested DSN exists yet.
+     *
+     * IMPORTANT: In order for MDB2 to work properly it is necessary that
+     * you make sure that you work with a reference of the original
+     * object instead of a copy (this is a PHP4 quirk).
+     *
+     * For example:
+     *     $db =& MDB2::singleton($dsn);
+     *          ^^
+     * And not:
+     *     $db = MDB2::singleton($dsn);
+     *          ^^
+     *
+     * @param   mixed   'data source name', see the MDB2::parseDSN
+     *                            method for a description of the dsn format.
+     *                            Can also be specified as an array of the
+     *                            format returned by MDB2::parseDSN.
+     * @param   array   An associative array of option names and
+     *                            their values.
+     *
+     * @return  mixed   a newly created MDB2 connection object, or a MDB2
+     *                  error object on error
+     *
+     * @access  public
+     * @see     MDB2::parseDSN
+     */
+    function &singleton($dsn = null, $options = false)
+    {
+        if ($dsn) {
+            $dsninfo = MDB2::parseDSN($dsn);
+            $dsninfo = array_merge($GLOBALS['_MDB2_dsninfo_default'], $dsninfo);
+            $keys = array_keys($GLOBALS['_MDB2_databases']);
+            for ($i=0, $j=count($keys); $i<$j; ++$i) {
+                if (isset($GLOBALS['_MDB2_databases'][$keys[$i]])) {
+                    $tmp_dsn = $GLOBALS['_MDB2_databases'][$keys[$i]]->getDSN('array');
+                    if (count(array_diff_assoc($tmp_dsn, $dsninfo)) == 0) {
+                        MDB2::setOptions($GLOBALS['_MDB2_databases'][$keys[$i]], $options);
+                        return $GLOBALS['_MDB2_databases'][$keys[$i]];
+                    }
+                }
+            }
+        } elseif (is_array($GLOBALS['_MDB2_databases']) && reset($GLOBALS['_MDB2_databases'])) {
+            $db =& $GLOBALS['_MDB2_databases'][key($GLOBALS['_MDB2_databases'])];
+            return $db;
+        }
+        $db =& MDB2::factory($dsn, $options);
+        return $db;
+    }
+
+    // }}}
+    // {{{ function loadFile($file)
+
+    /**
+     * load a file (like 'Date')
+     *
+     * @param   string  name of the file in the MDB2 directory (without '.php')
+     *
+     * @return  string  name of the file that was included
+     *
+     * @access  public
+     */
+    function loadFile($file)
+    {
+        $file_name = 'MDB2'.DIRECTORY_SEPARATOR.$file.'.php';
+        if (!MDB2::fileExists($file_name)) {
+            return MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'unable to find: '.$file_name);
+        }
+        if (!include_once($file_name)) {
+            return MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'unable to load driver class: '.$file_name);
+        }
+        return $file_name;
+    }
+
+    // }}}
+    // {{{ function apiVersion()
+
+    /**
+     * Return the MDB2 API version
+     *
+     * @return  string  the MDB2 API version number
+     *
+     * @access  public
+     */
+    function apiVersion()
+    {
+        return '2.4.1';
+    }
+
+    // }}}
+    // {{{ function &raiseError($code = null, $mode = null, $options = null, $userinfo = null)
+
+    /**
+     * This method is used to communicate an error and invoke error
+     * callbacks etc.  Basically a wrapper for PEAR::raiseError
+     * without the message string.
+     *
+     * @param   mixed  int error code
+     *
+     * @param   int    error mode, see PEAR_Error docs
+     *
+     * @param   mixed  If error mode is PEAR_ERROR_TRIGGER, this is the
+     *                 error level (E_USER_NOTICE etc).  If error mode is
+     *                 PEAR_ERROR_CALLBACK, this is the callback function,
+     *                 either as a function name, or as an array of an
+     *                 object and method name.  For other error modes this
+     *                 parameter is ignored.
+     *
+     * @param   string Extra debug information.  Defaults to the last
+     *                 query and native error code.
+     *
+     * @return PEAR_Error instance of a PEAR Error object
+     *
+     * @access  private
+     * @see     PEAR_Error
+     */
+    function &raiseError($code = null, $mode = null, $options = null, $userinfo = null)
+    {
+        $err =& PEAR::raiseError(null, $code, $mode, $options, $userinfo, 'MDB2_Error', true);
+        return $err;
+    }
+
+    // }}}
+    // {{{ function isError($data, $code = null)
+
+    /**
+     * Tell whether a value is a MDB2 error.
+     *
+     * @param   mixed   the value to test
+     * @param   int     if is an error object, return true
+     *                        only if $code is a string and
+     *                        $db->getMessage() == $code or
+     *                        $code is an integer and $db->getCode() == $code
+     *
+     * @return  bool    true if parameter is an error
+     *
+     * @access  public
+     */
+    function isError($data, $code = null)
+    {
+        if (is_a($data, 'MDB2_Error')) {
+            if (is_null($code)) {
+                return true;
+            } elseif (is_string($code)) {
+                return $data->getMessage() === $code;
+            } else {
+                $code = (array)$code;
+                return in_array($data->getCode(), $code);
+            }
+        }
+        return false;
+    }
+
+    // }}}
+    // {{{ function isConnection($value)
+
+    /**
+     * Tell whether a value is a MDB2 connection
+     *
+     * @param   mixed   value to test
+     *
+     * @return  bool    whether $value is a MDB2 connection
+     *
+     * @access  public
+     */
+    function isConnection($value)
+    {
+        return is_a($value, 'MDB2_Driver_Common');
+    }
+
+    // }}}
+    // {{{ function isResult($value)
+
+    /**
+     * Tell whether a value is a MDB2 result
+     *
+     * @param   mixed   value to test
+     *
+     * @return  bool    whether $value is a MDB2 result
+     *
+     * @access  public
+     */
+    function isResult($value)
+    {
+        return is_a($value, 'MDB2_Result');
+    }
+
+    // }}}
+    // {{{ function isResultCommon($value)
+
+    /**
+     * Tell whether a value is a MDB2 result implementing the common interface
+     *
+     * @param   mixed   value to test
+     *
+     * @return  bool    whether $value is a MDB2 result implementing the common interface
+     *
+     * @access  public
+     */
+    function isResultCommon($value)
+    {
+        return is_a($value, 'MDB2_Result_Common');
+    }
+
+    // }}}
+    // {{{ function isStatement($value)
+
+    /**
+     * Tell whether a value is a MDB2 statement interface
+     *
+     * @param   mixed   value to test
+     *
+     * @return  bool    whether $value is a MDB2 statement interface
+     *
+     * @access  public
+     */
+    function isStatement($value)
+    {
+        return is_a($value, 'MDB2_Statement');
+    }
+
+    // }}}
+    // {{{ function errorMessage($value = null)
+
+    /**
+     * Return a textual error message for a MDB2 error code
+     *
+     * @param   int|array   integer error code,
+                                null to get the current error code-message map,
+                                or an array with a new error code-message map
+     *
+     * @return  string  error message, or false if the error code was
+     *                  not recognized
+     *
+     * @access  public
+     */
+    function errorMessage($value = null)
+    {
+        static $errorMessages;
+
+        if (is_array($value)) {
+            $errorMessages = $value;
+            return MDB2_OK;
+        }
+
+        if (!isset($errorMessages)) {
+            $errorMessages = array(
+                MDB2_OK                       => 'no error',
+                MDB2_ERROR                    => 'unknown error',
+                MDB2_ERROR_ALREADY_EXISTS     => 'already exists',
+                MDB2_ERROR_CANNOT_CREATE      => 'can not create',
+                MDB2_ERROR_CANNOT_ALTER       => 'can not alter',
+                MDB2_ERROR_CANNOT_REPLACE     => 'can not replace',
+                MDB2_ERROR_CANNOT_DELETE      => 'can not delete',
+                MDB2_ERROR_CANNOT_DROP        => 'can not drop',
+                MDB2_ERROR_CONSTRAINT         => 'constraint violation',
+                MDB2_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint',
+                MDB2_ERROR_DIVZERO            => 'division by zero',
+                MDB2_ERROR_INVALID            => 'invalid',
+                MDB2_ERROR_INVALID_DATE       => 'invalid date or time',
+                MDB2_ERROR_INVALID_NUMBER     => 'invalid number',
+                MDB2_ERROR_MISMATCH           => 'mismatch',
+                MDB2_ERROR_NODBSELECTED       => 'no database selected',
+                MDB2_ERROR_NOSUCHFIELD        => 'no such field',
+                MDB2_ERROR_NOSUCHTABLE        => 'no such table',
+                MDB2_ERROR_NOT_CAPABLE        => 'MDB2 backend not capable',
+                MDB2_ERROR_NOT_FOUND          => 'not found',
+                MDB2_ERROR_NOT_LOCKED         => 'not locked',
+                MDB2_ERROR_SYNTAX             => 'syntax error',
+                MDB2_ERROR_UNSUPPORTED        => 'not supported',
+                MDB2_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
+                MDB2_ERROR_INVALID_DSN        => 'invalid DSN',
+                MDB2_ERROR_CONNECT_FAILED     => 'connect failed',
+                MDB2_ERROR_NEED_MORE_DATA     => 'insufficient data supplied',
+                MDB2_ERROR_EXTENSION_NOT_FOUND=> 'extension not found',
+                MDB2_ERROR_NOSUCHDB           => 'no such database',
+                MDB2_ERROR_ACCESS_VIOLATION   => 'insufficient permissions',
+                MDB2_ERROR_LOADMODULE         => 'error while including on demand module',
+                MDB2_ERROR_TRUNCATED          => 'truncated',
+                MDB2_ERROR_DEADLOCK           => 'deadlock detected',
+            );
+        }
+
+        if (is_null($value)) {
+            return $errorMessages;
+        }
+
+        if (PEAR::isError($value)) {
+            $value = $value->getCode();
+        }
+
+        return isset($errorMessages[$value]) ?
+           $errorMessages[$value] : $errorMessages[MDB2_ERROR];
+    }
+
+    // }}}
+    // {{{ function parseDSN($dsn)
+
+    /**
+     * Parse a data source name.
+     *
+     * Additional keys can be added by appending a URI query string to the
+     * end of the DSN.
+     *
+     * The format of the supplied DSN is in its fullest form:
+     * <code>
+     *  phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true
+     * </code>
+     *
+     * Most variations are allowed:
+     * <code>
+     *  phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644
+     *  phptype://username:password@hostspec/database_name
+     *  phptype://username:password@hostspec
+     *  phptype://username@hostspec
+     *  phptype://hostspec/database
+     *  phptype://hostspec
+     *  phptype(dbsyntax)
+     *  phptype
+     * </code>
+     *
+     * @param   string  Data Source Name to be parsed
+     *
+     * @return  array   an associative array with the following keys:
+     *  + phptype:  Database backend used in PHP (mysql, odbc etc.)
+     *  + dbsyntax: Database used with regards to SQL syntax etc.
+     *  + protocol: Communication protocol to use (tcp, unix etc.)
+     *  + hostspec: Host specification (hostname[:port])
+     *  + database: Database to use on the DBMS server
+     *  + username: User name for login
+     *  + password: Password for login
+     *
+     * @access  public
+     * @author  Tomas V.V.Cox <cox@idecnet.com>
+     */
+    function parseDSN($dsn)
+    {
+        $parsed = $GLOBALS['_MDB2_dsninfo_default'];
+
+        if (is_array($dsn)) {
+            $dsn = array_merge($parsed, $dsn);
+            if (!$dsn['dbsyntax']) {
+                $dsn['dbsyntax'] = $dsn['phptype'];
+            }
+            return $dsn;
+        }
+
+        // Find phptype and dbsyntax
+        if (($pos = strpos($dsn, '://')) !== false) {
+            $str = substr($dsn, 0, $pos);
+            $dsn = substr($dsn, $pos + 3);
+        } else {
+            $str = $dsn;
+            $dsn = null;
+        }
+
+        // Get phptype and dbsyntax
+        // $str => phptype(dbsyntax)
+        if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
+            $parsed['phptype']  = $arr[1];
+            $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
+        } else {
+            $parsed['phptype']  = $str;
+            $parsed['dbsyntax'] = $str;
+        }
+
+        if (!count($dsn)) {
+            return $parsed;
+        }
+
+        // Get (if found): username and password
+        // $dsn => username:password@protocol+hostspec/database
+        if (($at = strrpos($dsn,'@')) !== false) {
+            $str = substr($dsn, 0, $at);
+            $dsn = substr($dsn, $at + 1);
+            if (($pos = strpos($str, ':')) !== false) {
+                $parsed['username'] = rawurldecode(substr($str, 0, $pos));
+                $parsed['password'] = rawurldecode(substr($str, $pos + 1));
+            } else {
+                $parsed['username'] = rawurldecode($str);
+            }
+        }
+
+        // Find protocol and hostspec
+
+        // $dsn => proto(proto_opts)/database
+        if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
+            $proto       = $match[1];
+            $proto_opts  = $match[2] ? $match[2] : false;
+            $dsn         = $match[3];
+
+        // $dsn => protocol+hostspec/database (old format)
+        } else {
+            if (strpos($dsn, '+') !== false) {
+                list($proto, $dsn) = explode('+', $dsn, 2);
+            }
+            if (   strpos($dsn, '//') === 0
+                && strpos($dsn, '/', 2) !== false
+                && $parsed['phptype'] == 'oci8'
+            ) {
+                //oracle's "Easy Connect" syntax:
+                //"username/password@[//]host[:port][/service_name]"
+                //e.g. "scott/tiger@//mymachine:1521/oracle"
+                $proto_opts = $dsn;
+                $dsn = null;
+            } elseif (strpos($dsn, '/') !== false) {
+                list($proto_opts, $dsn) = explode('/', $dsn, 2);
+            } else {
+                $proto_opts = $dsn;
+                $dsn = null;
+            }
+        }
+
+        // process the different protocol options
+        $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp';
+        $proto_opts = rawurldecode($proto_opts);
+        if (strpos($proto_opts, ':') !== false) {
+            list($proto_opts, $parsed['port']) = explode(':', $proto_opts);
+        }
+        if ($parsed['protocol'] == 'tcp') {
+            $parsed['hostspec'] = $proto_opts;
+        } elseif ($parsed['protocol'] == 'unix') {
+            $parsed['socket'] = $proto_opts;
+        }
+
+        // Get dabase if any
+        // $dsn => database
+        if ($dsn) {
+            // /database
+            if (($pos = strpos($dsn, '?')) === false) {
+                $parsed['database'] = $dsn;
+            // /database?param1=value1&param2=value2
+            } else {
+                $parsed['database'] = substr($dsn, 0, $pos);
+                $dsn = substr($dsn, $pos + 1);
+                if (strpos($dsn, '&') !== false) {
+                    $opts = explode('&', $dsn);
+                } else { // database?param1=value1
+                    $opts = array($dsn);
+                }
+                foreach ($opts as $opt) {
+                    list($key, $value) = explode('=', $opt);
+                    if (!isset($parsed[$key])) {
+                        // don't allow params overwrite
+                        $parsed[$key] = rawurldecode($value);
+                    }
+                }
+            }
+        }
+
+        return $parsed;
+    }
+
+    // }}}
+    // {{{ function fileExists($file)
+
+    /**
+     * Checks if a file exists in the include path
+     *
+     * @param   string  filename
+     *
+     * @return  bool    true success and false on error
+     *
+     * @access  public
+     */
+    function fileExists($file)
+    {
+        // safe_mode does notwork with is_readable()
+        if (!@ini_get('safe_mode')) {
+             $dirs = explode(PATH_SEPARATOR, ini_get('include_path'));
+             foreach ($dirs as $dir) {
+                 if (is_readable($dir . DIRECTORY_SEPARATOR . $file)) {
+                     return true;
+                 }
+            }
+        } else {
+            $fp = @fopen($file, 'r', true);
+            if (is_resource($fp)) {
+                @fclose($fp);
+                return true;
+            }
+        }
+        return false;
+    }
+    // }}}
+}
+
+// }}}
+// {{{ class MDB2_Error extends PEAR_Error
+
+/**
+ * MDB2_Error implements a class for reporting portable database error
+ * messages.
+ *
+ * @package     MDB2
+ * @category    Database
+ * @author Stig Bakken <ssb@fast.no>
+ */
+class MDB2_Error extends PEAR_Error
+{
+    // {{{ constructor: function MDB2_Error($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE, $debuginfo = null)
+
+    /**
+     * MDB2_Error constructor.
+     *
+     * @param   mixed   MDB2 error code, or string with error message.
+     * @param   int     what 'error mode' to operate in
+     * @param   int     what error level to use for $mode & PEAR_ERROR_TRIGGER
+     * @param   smixed   additional debug info, such as the last query
+     */
+    function MDB2_Error($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN,
+              $level = E_USER_NOTICE, $debuginfo = null)
+    {
+        if (is_null($code)) {
+            $code = MDB2_ERROR;
+        }
+        $this->PEAR_Error('MDB2 Error: '.MDB2::errorMessage($code), $code,
+            $mode, $level, $debuginfo);
+    }
+
+    // }}}
+}
+
+// }}}
+// {{{ class MDB2_Driver_Common extends PEAR
+
+/**
+ * MDB2_Driver_Common: Base class that is extended by each MDB2 driver
+ *
+ * @package     MDB2
+ * @category    Database
+ * @author      Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_Common extends PEAR
+{
+    // {{{ Variables (Properties)
+
+    /**
+     * index of the MDB2 object within the $GLOBALS['_MDB2_databases'] array
+     * @var     int
+     * @access  public
+     */
+    var $db_index = 0;
+
+    /**
+     * DSN used for the next query
+     * @var     array
+     * @access  protected
+     */
+    var $dsn = array();
+
+    /**
+     * DSN that was used to create the current connection
+     * @var     array
+     * @access  protected
+     */
+    var $connected_dsn = array();
+
+    /**
+     * connection resource
+     * @var     mixed
+     * @access  protected
+     */
+    var $connection = 0;
+
+    /**
+     * if the current opened connection is a persistent connection
+     * @var     bool
+     * @access  protected
+     */
+    var $opened_persistent;
+
+    /**
+     * the name of the database for the next query
+     * @var     string
+     * @access  protected
+     */
+    var $database_name = '';
+
+    /**
+     * the name of the database currently selected
+     * @var     string
+     * @access  protected
+     */
+    var $connected_database_name = '';
+
+    /**
+     * server version information
+     * @var     string
+     * @access  protected
+     */
+    var $connected_server_info = '';
+
+    /**
+     * list of all supported features of the given driver
+     * @var     array
+     * @access  public
+     */
+    var $supported = array(
+        'sequences' => false,
+        'indexes' => false,
+        'affected_rows' => false,
+        'summary_functions' => false,
+        'order_by_text' => false,
+        'transactions' => false,
+        'savepoints' => false,
+        'current_id' => false,
+        'limit_queries' => false,
+        'LOBs' => false,
+        'replace' => false,
+        'sub_selects' => false,
+        'auto_increment' => false,
+        'primary_key' => false,
+        'result_introspection' => false,
+        'prepared_statements' => false,
+        'identifier_quoting' => false,
+        'pattern_escaping' => false,
+        'new_link' => false,
+    );
+
+    /**
+     * Array of supported options that can be passed to the MDB2 instance.
+     * 
+     * The options can be set during object creation, using
+     * MDB2::connect(), MDB2::factory() or MDB2::singleton(). The options can 
+     * also be set after the object is created, using MDB2::setOptions() or 
+     * MDB2_Driver_Common::setOption().
+     * The list of available option includes:
+     * <ul>
+     *  <li>$options['ssl'] -> boolean: determines if ssl should be used for connections</li>
+     *  <li>$options['field_case'] -> CASE_LOWER|CASE_UPPER: determines what case to force on field/table names</li>
+     *  <li>$options['disable_query'] -> boolean: determines if queries should be executed</li>
+     *  <li>$options['result_class'] -> string: class used for result sets</li>
+     *  <li>$options['buffered_result_class'] -> string: class used for buffered result sets</li>
+     *  <li>$options['result_wrap_class'] -> string: class used to wrap result sets into</li>
+     *  <li>$options['result_buffering'] -> boolean should results be buffered or not?</li>
+     *  <li>$options['fetch_class'] -> string: class to use when fetch mode object is used</li>
+     *  <li>$options['persistent'] -> boolean: persistent connection?</li>
+     *  <li>$options['debug'] -> integer: numeric debug level</li>
+     *  <li>$options['debug_handler'] -> string: function/method that captures debug messages</li>
+     *  <li>$options['debug_expanded_output'] -> bool: BC option to determine if more context information should be send to the debug handler</li>
+     *  <li>$options['default_text_field_length'] -> integer: default text field length to use</li>
+     *  <li>$options['lob_buffer_length'] -> integer: LOB buffer length</li>
+     *  <li>$options['log_line_break'] -> string: line-break format</li>
+     *  <li>$options['idxname_format'] -> string: pattern for index name</li>
+     *  <li>$options['seqname_format'] -> string: pattern for sequence name</li>
+     *  <li>$options['savepoint_format'] -> string: pattern for auto generated savepoint names</li>
+     *  <li>$options['statement_format'] -> string: pattern for prepared statement names</li>
+     *  <li>$options['seqcol_name'] -> string: sequence column name</li>
+     *  <li>$options['quote_identifier'] -> boolean: if identifier quoting should be done when check_option is used</li>
+     *  <li>$options['use_transactions'] -> boolean: if transaction use should be enabled</li>
+     *  <li>$options['decimal_places'] -> integer: number of decimal places to handle</li>
+     *  <li>$options['portability'] -> integer: portability constant</li>
+     *  <li>$options['modules'] -> array: short to long module name mapping for __call()</li>
+     *  <li>$options['emulate_prepared'] -> boolean: force prepared statements to be emulated</li>
+     *  <li>$options['datatype_map'] -> array: map user defined datatypes to other primitive datatypes</li>
+     *  <li>$options['datatype_map_callback'] -> array: callback function/method that should be called</li>
+     * </ul>
+     *
+     * @var     array
+     * @access  public
+     * @see     MDB2::connect()
+     * @see     MDB2::factory()
+     * @see     MDB2::singleton()
+     * @see     MDB2_Driver_Common::setOption()
+     */
+    var $options = array(
+        'ssl' => false,
+        'field_case' => CASE_LOWER,
+        'disable_query' => false,
+        'result_class' => 'MDB2_Result_%s',
+        'buffered_result_class' => 'MDB2_BufferedResult_%s',
+        'result_wrap_class' => false,
+        'result_buffering' => true,
+        'fetch_class' => 'stdClass',
+        'persistent' => false,
+        'debug' => 0,
+        'debug_handler' => 'MDB2_defaultDebugOutput',
+        'debug_expanded_output' => false,
+        'default_text_field_length' => 4096,
+        'lob_buffer_length' => 8192,
+        'log_line_break' => "\n",
+        'idxname_format' => '%s_idx',
+        'seqname_format' => '%s_seq',
+        'savepoint_format' => 'MDB2_SAVEPOINT_%s',
+        'statement_format' => 'MDB2_STATEMENT_%1$s_%2$s',
+        'seqcol_name' => 'sequence',
+        'quote_identifier' => false,
+        'use_transactions' => true,
+        'decimal_places' => 2,
+        'portability' => MDB2_PORTABILITY_ALL,
+        'modules' => array(
+            'ex' => 'Extended',
+            'dt' => 'Datatype',
+            'mg' => 'Manager',
+            'rv' => 'Reverse',
+            'na' => 'Native',
+            'fc' => 'Function',
+        ),
+        'emulate_prepared' => false,
+        'datatype_map' => array(),
+        'datatype_map_callback' => array(),
+        'nativetype_map_callback' => array(),
+    );
+
+    /**
+     * string array
+     * @var     string
+     * @access  protected
+     */
+    var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => false, 'escape_pattern' => false);
+
+    /**
+     * identifier quoting
+     * @var     array
+     * @access  protected
+     */
+    var $identifier_quoting = array('start' => '"', 'end' => '"', 'escape' => '"');
+
+    /**
+     * sql comments
+     * @var     array
+     * @access  protected
+     */
+    var $sql_comments = array(
+        array('start' => '--', 'end' => "\n", 'escape' => false),
+        array('start' => '/*', 'end' => '*/', 'escape' => false),
+    );
+
+    /**
+     * comparision wildcards
+     * @var     array
+     * @access  protected
+     */
+    var $wildcards = array('%', '_');
+
+    /**
+     * column alias keyword
+     * @var     string
+     * @access  protected
+     */
+    var $as_keyword = ' AS ';
+
+    /**
+     * warnings
+     * @var     array
+     * @access  protected
+     */
+    var $warnings = array();
+
+    /**
+     * string with the debugging information
+     * @var     string
+     * @access  public
+     */
+    var $debug_output = '';
+
+    /**
+     * determine if there is an open transaction
+     * @var     bool
+     * @access  protected
+     */
+    var $in_transaction = false;
+
+    /**
+     * the smart transaction nesting depth
+     * @var     int
+     * @access  protected
+     */
+    var $nested_transaction_counter = null;
+
+    /**
+     * the first error that occured inside a nested transaction
+     * @var     MDB2_Error|bool
+     * @access  protected
+     */
+    var $has_transaction_error = false;
+
+    /**
+     * result offset used in the next query
+     * @var     int
+     * @access  protected
+     */
+    var $offset = 0;
+
+    /**
+     * result limit used in the next query
+     * @var     int
+     * @access  protected
+     */
+    var $limit = 0;
+
+    /**
+     * Database backend used in PHP (mysql, odbc etc.)
+     * @var     string
+     * @access  public
+     */
+    var $phptype;
+
+    /**
+     * Database used with regards to SQL syntax etc.
+     * @var     string
+     * @access  public
+     */
+    var $dbsyntax;
+
+    /**
+     * the last query sent to the driver
+     * @var     string
+     * @access  public
+     */
+    var $last_query;
+
+    /**
+     * the default fetchmode used
+     * @var     int
+     * @access  protected
+     */
+    var $fetchmode = MDB2_FETCHMODE_ORDERED;
+
+    /**
+     * array of module instances
+     * @var     array
+     * @access  protected
+     */
+    var $modules = array();
+
+    /**
+     * determines of the PHP4 destructor emulation has been enabled yet
+     * @var     array
+     * @access  protected
+     */
+    var $destructor_registered = true;
+
+    // }}}
+    // {{{ constructor: function __construct()
+
+    /**
+     * Constructor
+     */
+    function __construct()
+    {
+        end($GLOBALS['_MDB2_databases']);
+        $db_index = key($GLOBALS['_MDB2_databases']) + 1;
+        $GLOBALS['_MDB2_databases'][$db_index] = &$this;
+        $this->db_index = $db_index;
+    }
+
+    // }}}
+    // {{{ function MDB2_Driver_Common()
+
+    /**
+     * PHP 4 Constructor
+     */
+    function MDB2_Driver_Common()
+    {
+        $this->destructor_registered = false;
+        $this->__construct();
+    }
+
+    // }}}
+    // {{{ destructor: function __destruct()
+
+    /**
+     *  Destructor
+     */
+    function __destruct()
+    {
+        $this->disconnect(false);
+    }
+
+    // }}}
+    // {{{ function free()
+
+    /**
+     * Free the internal references so that the instance can be destroyed
+     *
+     * @return  bool    true on success, false if result is invalid
+     *
+     * @access  public
+     */
+    function free()
+    {
+        unset($GLOBALS['_MDB2_databases'][$this->db_index]);
+        unset($this->db_index);
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function __toString()
+
+    /**
+     * String conversation
+     *
+     * @return  string representation of the object
+     *
+     * @access  public
+     */
+    function __toString()
+    {
+        $info = get_class($this);
+        $info.= ': (phptype = '.$this->phptype.', dbsyntax = '.$this->dbsyntax.')';
+        if ($this->connection) {
+            $info.= ' [connected]';
+        }
+        return $info;
+    }
+
+    // }}}
+    // {{{ function errorInfo($error = null)
+
+    /**
+     * This method is used to collect information about an error
+     *
+     * @param   mixed   error code or resource
+     *
+     * @return  array   with MDB2 errorcode, native error code, native message
+     *
+     * @access  public
+     */
+    function errorInfo($error = null)
+    {
+        return array($error, null, null);
+    }
+
+    // }}}
+    // {{{ function &raiseError($code = null, $mode = null, $options = null, $userinfo = null)
+
+    /**
+     * This method is used to communicate an error and invoke error
+     * callbacks etc.  Basically a wrapper for PEAR::raiseError
+     * without the message string.
+     *
+     * @param   mixed   integer error code, or a PEAR error object (all other
+     *                  parameters are ignored if this parameter is an object
+     * @param   int     error mode, see PEAR_Error docs
+     * @param   mixed   If error mode is PEAR_ERROR_TRIGGER, this is the
+         *              error level (E_USER_NOTICE etc).  If error mode is
+     *                  PEAR_ERROR_CALLBACK, this is the callback function,
+     *                  either as a function name, or as an array of an
+     *                  object and method name.  For other error modes this
+     *                  parameter is ignored.
+     * @param   string  Extra debug information.  Defaults to the last
+     *                  query and native error code.
+     * @param   string  name of the method that triggered the error
+     *
+     * @return PEAR_Error   instance of a PEAR Error object
+     *
+     * @access  public
+     * @see     PEAR_Error
+     */
+    function &raiseError($code = null, $mode = null, $options = null, $userinfo = null, $method = null)
+    {
+        $userinfo = "[Error message: $userinfo]\n";
+        // The error is yet a MDB2 error object
+        if (PEAR::isError($code)) {
+            // because we use the static PEAR::raiseError, our global
+            // handler should be used if it is set
+            if (is_null($mode) && !empty($this->_default_error_mode)) {
+                $mode    = $this->_default_error_mode;
+                $options = $this->_default_error_options;
+            }
+            if (is_null($userinfo)) {
+                $userinfo = $code->getUserinfo();
+            }
+            $code = $code->getCode();
+        } elseif ($code == MDB2_ERROR_NOT_FOUND) {
+            // extension not loaded: don't call $this->errorInfo() or the script
+            // will die
+        } elseif (isset($this->connection)) {
+            if (!empty($this->last_query)) {
+                $userinfo.= "[Last executed query: {$this->last_query}]\n";
+            }
+            $native_errno = $native_msg = null;
+            list($code, $native_errno, $native_msg) = $this->errorInfo($code);
+            if (!is_null($native_errno) && $native_errno !== '') {
+                $userinfo.= "[Native code: $native_errno]\n";
+            }
+            if (!is_null($native_msg) && $native_msg !== '') {
+                $userinfo.= "[Native message: ". strip_tags($native_msg) ."]\n";
+            }
+            if (!is_null($method)) {
+                $userinfo = $method.': '.$userinfo;
+            }
+        }
+
+        $err =& PEAR::raiseError(null, $code, $mode, $options, $userinfo, 'MDB2_Error', true);
+        if ($err->getMode() !== PEAR_ERROR_RETURN
+            && isset($this->nested_transaction_counter) && !$this->has_transaction_error) {
+            $this->has_transaction_error =& $err;
+        }
+        return $err;
+    }
+
+    // }}}
+    // {{{ function resetWarnings()
+
+    /**
+     * reset the warning array
+     *
+     * @return void
+     *
+     * @access  public
+     */
+    function resetWarnings()
+    {
+        $this->warnings = array();
+    }
+
+    // }}}
+    // {{{ function getWarnings()
+
+    /**
+     * Get all warnings in reverse order.
+     * This means that the last warning is the first element in the array
+     *
+     * @return  array   with warnings
+     *
+     * @access  public
+     * @see     resetWarnings()
+     */
+    function getWarnings()
+    {
+        return array_reverse($this->warnings);
+    }
+
+    // }}}
+    // {{{ function setFetchMode($fetchmode, $object_class = 'stdClass')
+
+    /**
+     * Sets which fetch mode should be used by default on queries
+     * on this connection
+     *
+     * @param   int     MDB2_FETCHMODE_ORDERED, MDB2_FETCHMODE_ASSOC
+     *                               or MDB2_FETCHMODE_OBJECT
+     * @param   string  the class name of the object to be returned
+     *                               by the fetch methods when the
+     *                               MDB2_FETCHMODE_OBJECT mode is selected.
+     *                               If no class is specified by default a cast
+     *                               to object from the assoc array row will be
+     *                               done.  There is also the possibility to use
+     *                               and extend the 'MDB2_row' class.
+     *
+     * @return  mixed   MDB2_OK or MDB2 Error Object
+     *
+     * @access  public
+     * @see     MDB2_FETCHMODE_ORDERED, MDB2_FETCHMODE_ASSOC, MDB2_FETCHMODE_OBJECT
+     */
+    function setFetchMode($fetchmode, $object_class = 'stdClass')
+    {
+        switch ($fetchmode) {
+        case MDB2_FETCHMODE_OBJECT:
+            $this->options['fetch_class'] = $object_class;
+        case MDB2_FETCHMODE_ORDERED:
+        case MDB2_FETCHMODE_ASSOC:
+            $this->fetchmode = $fetchmode;
+            break;
+        default:
+            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'invalid fetchmode mode', __FUNCTION__);
+        }
+
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function setOption($option, $value)
+
+    /**
+     * set the option for the db class
+     *
+     * @param   string  option name
+     * @param   mixed   value for the option
+     *
+     * @return  mixed   MDB2_OK or MDB2 Error Object
+     *
+     * @access  public
+     */
+    function setOption($option, $value)
+    {
+        if (array_key_exists($option, $this->options)) {
+            $this->options[$option] = $value;
+            return MDB2_OK;
+        }
+        return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            "unknown option $option", __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function getOption($option)
+
+    /**
+     * Returns the value of an option
+     *
+     * @param   string  option name
+     *
+     * @return  mixed   the option value or error object
+     *
+     * @access  public
+     */
+    function getOption($option)
+    {
+        if (array_key_exists($option, $this->options)) {
+            return $this->options[$option];
+        }
+        return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            "unknown option $option", __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function debug($message, $scope = '', $is_manip = null)
+
+    /**
+     * set a debug message
+     *
+     * @param   string  message that should be appended to the debug variable
+     * @param   string  usually the method name that triggered the debug call:
+     *                  for example 'query', 'prepare', 'execute', 'parameters',
+     *                  'beginTransaction', 'commit', 'rollback'
+     * @param   array   contains context information about the debug() call
+     *                  common keys are: is_manip, time, result etc.
+     *
+     * @return void
+     *
+     * @access  public
+     */
+    function debug($message, $scope = '', $context = array())
+    {
+        if ($this->options['debug'] && $this->options['debug_handler']) {
+            if (!$this->options['debug_expanded_output']) {
+                if (!empty($context['when']) && $context['when'] !== 'pre') {
+                    return null;
+                }
+                $context = empty($context['is_manip']) ? false : $context['is_manip'];
+            }
+            return call_user_func_array($this->options['debug_handler'], array(&$this, $scope, $message, $context));
+        }
+        return null;
+    }
+
+    // }}}
+    // {{{ function getDebugOutput()
+
+    /**
+     * output debug info
+     *
+     * @return  string  content of the debug_output class variable
+     *
+     * @access  public
+     */
+    function getDebugOutput()
+    {
+        return $this->debug_output;
+    }
+
+    // }}}
+    // {{{ function escape($text)
+
+    /**
+     * Quotes a string so it can be safely used in a query. It will quote
+     * the text so it can safely be used within a query.
+     *
+     * @param   string  the input string to quote
+     * @param   bool    escape wildcards
+     *
+     * @return  string  quoted string
+     *
+     * @access  public
+     */
+    function escape($text, $escape_wildcards = false)
+    {
+        if ($escape_wildcards) {
+            $text = $this->escapePattern($text);
+        }
+
+        $text = str_replace($this->string_quoting['end'], $this->string_quoting['escape'] . $this->string_quoting['end'], $text);
+        return $text;
+    }
+
+    // }}}
+    // {{{ function escapePattern($text)
+
+    /**
+     * Quotes pattern (% and _) characters in a string)
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change signature at
+     * any time until labelled as non-experimental
+     *
+     * @param   string  the input string to quote
+     *
+     * @return  string  quoted string
+     *
+     * @access  public
+     */
+    function escapePattern($text)
+    {
+        if ($this->string_quoting['escape_pattern']) {
+            $text = str_replace($this->string_quoting['escape_pattern'], $this->string_quoting['escape_pattern'] . $this->string_quoting['escape_pattern'], $text);
+            foreach ($this->wildcards as $wildcard) {
+                $text = str_replace($wildcard, $this->string_quoting['escape_pattern'] . $wildcard, $text);
+            }
+        }
+        return $text;
+    }
+
+    // }}}
+    // {{{ function quoteIdentifier($str, $check_option = false)
+
+    /**
+     * Quote a string so it can be safely used as a table or column name
+     *
+     * Delimiting style depends on which database driver is being used.
+     *
+     * NOTE: just because you CAN use delimited identifiers doesn't mean
+     * you SHOULD use them.  In general, they end up causing way more
+     * problems than they solve.
+     *
+     * Portability is broken by using the following characters inside
+     * delimited identifiers:
+     *   + backtick (<kbd>`</kbd>) -- due to MySQL
+     *   + double quote (<kbd>"</kbd>) -- due to Oracle
+     *   + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access
+     *
+     * Delimited identifiers are known to generally work correctly under
+     * the following drivers:
+     *   + mssql
+     *   + mysql
+     *   + mysqli
+     *   + oci8
+     *   + pgsql
+     *   + sqlite
+     *
+     * InterBase doesn't seem to be able to use delimited identifiers
+     * via PHP 4.  They work fine under PHP 5.
+     *
+     * @param   string  identifier name to be quoted
+     * @param   bool    check the 'quote_identifier' option
+     *
+     * @return  string  quoted identifier string
+     *
+     * @access  public
+     */
+    function quoteIdentifier($str, $check_option = false)
+    {
+        if ($check_option && !$this->options['quote_identifier']) {
+            return $str;
+        }
+        $str = str_replace($this->identifier_quoting['end'], $this->identifier_quoting['escape'] . $this->identifier_quoting['end'], $str);
+        return $this->identifier_quoting['start'] . $str . $this->identifier_quoting['end'];
+    }
+
+    // }}}
+    // {{{ function getAsKeyword()
+
+    /**
+     * Gets the string to alias column
+     *
+     * @return string to use when aliasing a column
+     */
+    function getAsKeyword()
+    {
+        return $this->as_keyword;
+    }
+
+    // }}}
+    // {{{ function getConnection()
+
+    /**
+     * Returns a native connection
+     *
+     * @return  mixed   a valid MDB2 connection object,
+     *                  or a MDB2 error object on error
+     *
+     * @access  public
+     */
+    function getConnection()
+    {
+        $result = $this->connect();
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        return $this->connection;
+    }
+
+     // }}}
+    // {{{ function _fixResultArrayValues(&$row, $mode)
+
+    /**
+     * Do all necessary conversions on result arrays to fix DBMS quirks
+     *
+     * @param   array   the array to be fixed (passed by reference)
+     * @param   array   bit-wise addition of the required portability modes
+     *
+     * @return  void
+     *
+     * @access  protected
+     */
+    function _fixResultArrayValues(&$row, $mode)
+    {
+        switch ($mode) {
+        case MDB2_PORTABILITY_EMPTY_TO_NULL:
+            foreach ($row as $key => $value) {
+                if ($value === '') {
+                    $row[$key] = null;
+                }
+            }
+            break;
+        case MDB2_PORTABILITY_RTRIM:
+            foreach ($row as $key => $value) {
+                if (is_string($value)) {
+                    $row[$key] = rtrim($value);
+                }
+            }
+            break;
+        case MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES:
+            $tmp_row = array();
+            foreach ($row as $key => $value) {
+                $tmp_row[preg_replace('/^(?:.*\.)?([^.]+)$/', '\\1', $key)] = $value;
+            }
+            $row = $tmp_row;
+            break;
+        case (MDB2_PORTABILITY_RTRIM + MDB2_PORTABILITY_EMPTY_TO_NULL):
+            foreach ($row as $key => $value) {
+                if ($value === '') {
+                    $row[$key] = null;
+                } elseif (is_string($value)) {
+                    $row[$key] = rtrim($value);
+                }
+            }
+            break;
+        case (MDB2_PORTABILITY_RTRIM + MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES):
+            $tmp_row = array();
+            foreach ($row as $key => $value) {
+                if (is_string($value)) {
+                    $value = rtrim($value);
+                }
+                $tmp_row[preg_replace('/^(?:.*\.)?([^.]+)$/', '\\1', $key)] = $value;
+            }
+            $row = $tmp_row;
+            break;
+        case (MDB2_PORTABILITY_EMPTY_TO_NULL + MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES):
+            $tmp_row = array();
+            foreach ($row as $key => $value) {
+                if ($value === '') {
+                    $value = null;
+                }
+                $tmp_row[preg_replace('/^(?:.*\.)?([^.]+)$/', '\\1', $key)] = $value;
+            }
+            $row = $tmp_row;
+            break;
+        case (MDB2_PORTABILITY_RTRIM + MDB2_PORTABILITY_EMPTY_TO_NULL + MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES):
+            $tmp_row = array();
+            foreach ($row as $key => $value) {
+                if ($value === '') {
+                    $value = null;
+                } elseif (is_string($value)) {
+                    $value = rtrim($value);
+                }
+                $tmp_row[preg_replace('/^(?:.*\.)?([^.]+)$/', '\\1', $key)] = $value;
+            }
+            $row = $tmp_row;
+            break;
+        }
+    }
+
+    // }}}
+    // {{{ function &loadModule($module, $property = null, $phptype_specific = null)
+
+    /**
+     * loads a module
+     *
+     * @param   string  name of the module that should be loaded
+     *                  (only used for error messages)
+     * @param   string  name of the property into which the class will be loaded
+     * @param   bool    if the class to load for the module is specific to the
+     *                  phptype
+     *
+     * @return  object  on success a reference to the given module is returned
+     *                  and on failure a PEAR error
+     *
+     * @access  public
+     */
+    function &loadModule($module, $property = null, $phptype_specific = null)
+    {
+        if (!$property) {
+            $property = strtolower($module);
+        }
+
+        if (!isset($this->{$property})) {
+            $version = $phptype_specific;
+            if ($phptype_specific !== false) {
+                $version = true;
+                $class_name = 'MDB2_Driver_'.$module.'_'.$this->phptype;
+                $file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name).'.php';
+            }
+            if ($phptype_specific === false
+                || (!MDB2::classExists($class_name) && !MDB2::fileExists($file_name))
+            ) {
+                $version = false;
+                $class_name = 'MDB2_'.$module;
+                $file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name).'.php';
+            }
+
+            $err = MDB2::loadClass($class_name, $this->getOption('debug'));
+            if (PEAR::isError($err)) {
+                return $err;
+            }
+
+            // load modul in a specific version
+            if ($version) {
+                if (method_exists($class_name, 'getClassName')) {
+                    $class_name_new = call_user_func(array($class_name, 'getClassName'), $this->db_index);
+                    if ($class_name != $class_name_new) {
+                        $class_name = $class_name_new;
+                        $err = MDB2::loadClass($class_name, $this->getOption('debug'));
+                        if (PEAR::isError($err)) {
+                            return $err;
+                        }
+                    }
+                }
+            }
+
+            if (!MDB2::classExists($class_name)) {
+                $err =& $this->raiseError(MDB2_ERROR_LOADMODULE, null, null,
+                    "unable to load module '$module' into property '$property'", __FUNCTION__);
+                return $err;
+            }
+            $this->{$property} =& new $class_name($this->db_index);
+            $this->modules[$module] =& $this->{$property};
+            if ($version) {
+                // this will be used in the connect method to determine if the module
+                // needs to be loaded with a different version if the server
+                // version changed in between connects
+                $this->loaded_version_modules[] = $property;
+            }
+        }
+
+        return $this->{$property};
+    }
+
+    // }}}
+    // {{{ function __call($method, $params)
+
+    /**
+     * Calls a module method using the __call magic method
+     *
+     * @param   string  Method name.
+     * @param   array   Arguments.
+     *
+     * @return  mixed   Returned value.
+     */
+    function __call($method, $params)
+    {
+        $module = null;
+        if (preg_match('/^([a-z]+)([A-Z])(.*)$/', $method, $match)
+            && isset($this->options['modules'][$match[1]])
+        ) {
+            $module = $this->options['modules'][$match[1]];
+            $method = strtolower($match[2]).$match[3];
+            if (!isset($this->modules[$module]) || !is_object($this->modules[$module])) {
+                $result =& $this->loadModule($module);
+                if (PEAR::isError($result)) {
+                    return $result;
+                }
+            }
+        } else {
+            foreach ($this->modules as $key => $foo) {
+                if (is_object($this->modules[$key])
+                    && method_exists($this->modules[$key], $method)
+                ) {
+                    $module = $key;
+                    break;
+                }
+            }
+        }
+        if (!is_null($module)) {
+            return call_user_func_array(array(&$this->modules[$module], $method), $params);
+        }
+        trigger_error(sprintf('Call to undefined function: %s::%s().', get_class($this), $method), E_USER_ERROR);
+    }
+
+    // }}}
+    // {{{ function beginTransaction($savepoint = null)
+
+    /**
+     * Start a transaction or set a savepoint.
+     *
+     * @param   string  name of a savepoint to set
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function beginTransaction($savepoint = null)
+    {
+        $this->debug('Starting transaction', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
+        return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'transactions are not supported', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function commit($savepoint = null)
+
+    /**
+     * Commit the database changes done during a transaction that is in
+     * progress or release a savepoint. This function may only be called when
+     * auto-committing is disabled, otherwise it will fail. Therefore, a new
+     * transaction is implicitly started after committing the pending changes.
+     *
+     * @param   string  name of a savepoint to release
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function commit($savepoint = null)
+    {
+        $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
+        return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'commiting transactions is not supported', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function rollback($savepoint = null)
+
+    /**
+     * Cancel any database changes done during a transaction or since a specific
+     * savepoint that is in progress. This function may only be called when
+     * auto-committing is disabled, otherwise it will fail. Therefore, a new
+     * transaction is implicitly started after canceling the pending changes.
+     *
+     * @param   string  name of a savepoint to rollback to
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function rollback($savepoint = null)
+    {
+        $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
+        return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'rolling back transactions is not supported', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function inTransaction($ignore_nested = false)
+
+    /**
+     * If a transaction is currently open.
+     *
+     * @param   bool    if the nested transaction count should be ignored
+     * @return  int|bool    - an integer with the nesting depth is returned if a
+     *                      nested transaction is open
+     *                      - true is returned for a normal open transaction
+     *                      - false is returned if no transaction is open
+     *
+     * @access  public
+     */
+    function inTransaction($ignore_nested = false)
+    {
+        if (!$ignore_nested && isset($this->nested_transaction_counter)) {
+            return $this->nested_transaction_counter;
+        }
+        return $this->in_transaction;
+    }
+
+    // }}}
+    // {{{ function setTransactionIsolation($isolation)
+
+    /**
+     * Set the transacton isolation level.
+     *
+     * @param   string  standard isolation level
+     *                  READ UNCOMMITTED (allows dirty reads)
+     *                  READ COMMITTED (prevents dirty reads)
+     *                  REPEATABLE READ (prevents nonrepeatable reads)
+     *                  SERIALIZABLE (prevents phantom reads)
+     * @param   array some transaction options:
+     *                  'wait' => 'WAIT' | 'NO WAIT'
+     *                  'rw'   => 'READ WRITE' | 'READ ONLY'
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     * @since   2.1.1
+     */
+    function setTransactionIsolation($isolation, $options = array())
+    {
+        $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true));
+        return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'isolation level setting is not supported', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function beginNestedTransaction($savepoint = false)
+
+    /**
+     * Start a nested transaction.
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change signature at
+     * any time until labelled as non-experimental
+     *
+     * @return  mixed   MDB2_OK on success/savepoint name, a MDB2 error on failure
+     *
+     * @access  public
+     * @since   2.1.1
+     */
+    function beginNestedTransaction()
+    {
+        if ($this->in_transaction) {
+            ++$this->nested_transaction_counter;
+            $savepoint = sprintf($this->options['savepoint_format'], $this->nested_transaction_counter);
+            if ($this->supports('savepoints') && $savepoint) {
+                return $this->beginTransaction($savepoint);
+            }
+            return MDB2_OK;
+        }
+        $this->has_transaction_error = false;
+        $result = $this->beginTransaction();
+        $this->nested_transaction_counter = 1;
+        return $result;
+    }
+
+    // }}}
+    // {{{ function completeNestedTransaction($force_rollback = false, $release = false)
+
+    /**
+     * Finish a nested transaction by rolling back if an error occured or
+     * committing otherwise.
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change signature at
+     * any time until labelled as non-experimental
+     *
+     * @param   bool    if the transaction should be rolled back regardless
+     *                  even if no error was set within the nested transaction
+     * @return  mixed   MDB_OK on commit/counter decrementing, false on rollback
+     *                  and a MDB2 error on failure
+     *
+     * @access  public
+     * @since   2.1.1
+     */
+    function completeNestedTransaction($force_rollback = false)
+    {
+        if ($this->nested_transaction_counter > 1) {
+            $savepoint = sprintf($this->options['savepoint_format'], $this->nested_transaction_counter);
+            if ($this->supports('savepoints') && $savepoint) {
+                if ($force_rollback || $this->has_transaction_error) {
+                    $result = $this->rollback($savepoint);
+                    if (!PEAR::isError($result)) {
+                        $result = false;
+                        $this->has_transaction_error = false;
+                    }
+                } else {
+                    $result = $this->commit($savepoint);
+                }
+            } else {
+                $result = MDB2_OK;
+            }
+            --$this->nested_transaction_counter;
+            return $result;
+        }
+
+        $this->nested_transaction_counter = null;
+        $result = MDB2_OK;
+
+        // transaction has not yet been rolled back
+        if ($this->in_transaction) {
+            if ($force_rollback || $this->has_transaction_error) {
+                $result = $this->rollback();
+                if (!PEAR::isError($result)) {
+                    $result = false;
+                }
+            } else {
+                $result = $this->commit();
+            }
+        }
+        $this->has_transaction_error = false;
+        return $result;
+    }
+
+    // }}}
+    // {{{ function failNestedTransaction($error = null, $immediately = false)
+
+    /**
+     * Force setting nested transaction to failed.
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change signature at
+     * any time until labelled as non-experimental
+     *
+     * @param   mixed   value to return in getNestededTransactionError()
+     * @param   bool    if the transaction should be rolled back immediately
+     * @return  bool    MDB2_OK
+     *
+     * @access  public
+     * @since   2.1.1
+     */
+    function failNestedTransaction($error = null, $immediately = false)
+    {
+        if (is_null($error)) {
+            $error = $this->has_transaction_error ? $this->has_transaction_error : true;
+        } elseif (!$error) {
+            $error = true;
+        }
+        $this->has_transaction_error = $error;
+        if (!$immediately) {
+            return MDB2_OK;
+        }
+        return $this->rollback();
+    }
+
+    // }}}
+    // {{{ function getNestedTransactionError()
+
+    /**
+     * The first error that occured since the transaction start.
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change signature at
+     * any time until labelled as non-experimental
+     *
+     * @return  MDB2_Error|bool     MDB2 error object if an error occured or false.
+     *
+     * @access  public
+     * @since   2.1.1
+     */
+    function getNestedTransactionError()
+    {
+        return $this->has_transaction_error;
+    }
+
+    // }}}
+    // {{{ connect()
+
+    /**
+     * Connect to the database
+     *
+     * @return true on success, MDB2 Error Object on failure
+     */
+    function connect()
+    {
+        return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ setCharset($charset, $connection = null)
+
+    /**
+     * Set the charset on the current connection
+     *
+     * @param string    charset
+     * @param resource  connection handle
+     *
+     * @return true on success, MDB2 Error Object on failure
+     */
+    function setCharset($charset, $connection = null)
+    {
+        return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function disconnect($force = true)
+
+    /**
+     * Log out and disconnect from the database.
+     *
+     * @param   bool    if the disconnect should be forced even if the
+     *                  connection is opened persistently
+     *
+     * @return  mixed   true on success, false if not connected and error
+     *                  object on error
+     *
+     * @access  public
+     */
+    function disconnect($force = true)
+    {
+        $this->connection = 0;
+        $this->connected_dsn = array();
+        $this->connected_database_name = '';
+        $this->opened_persistent = null;
+        $this->connected_server_info = '';
+        $this->in_transaction = null;
+        $this->nested_transaction_counter = null;
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function setDatabase($name)
+
+    /**
+     * Select a different database
+     *
+     * @param   string  name of the database that should be selected
+     *
+     * @return  string  name of the database previously connected to
+     *
+     * @access  public
+     */
+    function setDatabase($name)
+    {
+        $previous_database_name = (isset($this->database_name)) ? $this->database_name : '';
+        $this->database_name = $name;
+        $this->disconnect(false);
+        return $previous_database_name;
+    }
+
+    // }}}
+    // {{{ function getDatabase()
+
+    /**
+     * Get the current database
+     *
+     * @return  string  name of the database
+     *
+     * @access  public
+     */
+    function getDatabase()
+    {
+        return $this->database_name;
+    }
+
+    // }}}
+    // {{{ function setDSN($dsn)
+
+    /**
+     * set the DSN
+     *
+     * @param   mixed   DSN string or array
+     *
+     * @return  MDB2_OK
+     *
+     * @access  public
+     */
+    function setDSN($dsn)
+    {
+        $dsn_default = $GLOBALS['_MDB2_dsninfo_default'];
+        $dsn = MDB2::parseDSN($dsn);
+        if (array_key_exists('database', $dsn)) {
+            $this->database_name = $dsn['database'];
+            unset($dsn['database']);
+        }
+        $this->dsn = array_merge($dsn_default, $dsn);
+        return $this->disconnect(false);
+    }
+
+    // }}}
+    // {{{ function getDSN($type = 'string', $hidepw = false)
+
+    /**
+     * return the DSN as a string
+     *
+     * @param   string  format to return ("array", "string")
+     * @param   string  string to hide the password with
+     *
+     * @return  mixed   DSN in the chosen type
+     *
+     * @access  public
+     */
+    function getDSN($type = 'string', $hidepw = false)
+    {
+        $dsn = array_merge($GLOBALS['_MDB2_dsninfo_default'], $this->dsn);
+        $dsn['phptype'] = $this->phptype;
+        $dsn['database'] = $this->database_name;
+        if ($hidepw) {
+            $dsn['password'] = $hidepw;
+        }
+        switch ($type) {
+        // expand to include all possible options
+        case 'string':
+           $dsn = $dsn['phptype'].
+               ($dsn['dbsyntax'] ? ('('.$dsn['dbsyntax'].')') : '').
+               '://'.$dsn['username'].':'.
+                $dsn['password'].'@'.$dsn['hostspec'].
+                ($dsn['port'] ? (':'.$dsn['port']) : '').
+                '/'.$dsn['database'];
+            break;
+        case 'array':
+        default:
+            break;
+        }
+        return $dsn;
+    }
+
+    // }}}
+    // {{{ function &standaloneQuery($query, $types = null, $is_manip = false)
+
+   /**
+     * execute a query as database administrator
+     *
+     * @param   string  the SQL query
+     * @param   mixed   array that contains the types of the columns in
+     *                        the result set
+     * @param   bool    if the query is a manipulation query
+     *
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function &standaloneQuery($query, $types = null, $is_manip = false)
+    {
+        $offset = $this->offset;
+        $limit = $this->limit;
+        $this->offset = $this->limit = 0;
+        $query = $this->_modifyQuery($query, $is_manip, $limit, $offset);
+
+        $connection = $this->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+
+        $result =& $this->_doQuery($query, $is_manip, $connection, false);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+
+        if ($is_manip) {
+            $affected_rows =  $this->_affectedRows($connection, $result);
+            return $affected_rows;
+        }
+        $result =& $this->_wrapResult($result, $types, true, false, $limit, $offset);
+        return $result;
+    }
+
+    // }}}
+    // {{{ function _modifyQuery($query, $is_manip, $limit, $offset)
+
+    /**
+     * Changes a query string for various DBMS specific reasons
+     *
+     * @param   string  query to modify
+     * @param   bool    if it is a DML query
+     * @param   int  limit the number of rows
+     * @param   int  start reading from given offset
+     *
+     * @return  string  modified query
+     *
+     * @access  protected
+     */
+    function _modifyQuery($query, $is_manip, $limit, $offset)
+    {
+        return $query;
+    }
+
+    // }}}
+    // {{{ function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null)
+
+    /**
+     * Execute a query
+     * @param   string  query
+     * @param   bool    if the query is a manipulation query
+     * @param   resource connection handle
+     * @param   string  database name
+     *
+     * @return  result or error object
+     *
+     * @access  protected
+     */
+    function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null)
+    {
+        $this->last_query = $query;
+        $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre'));
+        if ($result) {
+            if (PEAR::isError($result)) {
+                return $result;
+            }
+            $query = $result;
+        }
+        $err =& $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+        return $err;
+    }
+
+    // }}}
+    // {{{ function _affectedRows($connection, $result = null)
+
+    /**
+     * Returns the number of rows affected
+     *
+     * @param   resource result handle
+     * @param   resource connection handle
+     *
+     * @return  mixed   MDB2 Error Object or the number of rows affected
+     *
+     * @access  private
+     */
+    function _affectedRows($connection, $result = null)
+    {
+        return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function &exec($query)
+
+    /**
+     * Execute a manipulation query to the database and return the number of affected rows
+     *
+     * @param   string  the SQL query
+     *
+     * @return  mixed   number of affected rows on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function &exec($query)
+    {
+        $offset = $this->offset;
+        $limit = $this->limit;
+        $this->offset = $this->limit = 0;
+        $query = $this->_modifyQuery($query, true, $limit, $offset);
+
+        $connection = $this->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+
+        $result =& $this->_doQuery($query, true, $connection, $this->database_name);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+
+        $affectedRows = $this->_affectedRows($connection, $result);
+        return $affectedRows;
+    }
+
+    // }}}
+    // {{{ function &query($query, $types = null, $result_class = true, $result_wrap_class = false)
+
+    /**
+     * Send a query to the database and return any results
+     *
+     * @param   string  the SQL query
+     * @param   mixed   array that contains the types of the columns in
+     *                        the result set
+     * @param   mixed   string which specifies which result class to use
+     * @param   mixed   string which specifies which class to wrap results in
+     *
+     * @return mixed   an MDB2_Result handle on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function &query($query, $types = null, $result_class = true, $result_wrap_class = false)
+    {
+        $offset = $this->offset;
+        $limit = $this->limit;
+        $this->offset = $this->limit = 0;
+        $query = $this->_modifyQuery($query, false, $limit, $offset);
+
+        $connection = $this->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+
+        $result =& $this->_doQuery($query, false, $connection, $this->database_name);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+
+        $result =& $this->_wrapResult($result, $types, $result_class, $result_wrap_class, $limit, $offset);
+        return $result;
+    }
+
+    // }}}
+    // {{{ function &_wrapResult($result, $types = array(), $result_class = true, $result_wrap_class = false, $limit = null, $offset = null)
+
+    /**
+     * wrap a result set into the correct class
+     *
+     * @param   resource result handle
+     * @param   mixed   array that contains the types of the columns in
+     *                        the result set
+     * @param   mixed   string which specifies which result class to use
+     * @param   mixed   string which specifies which class to wrap results in
+     * @param   string  number of rows to select
+     * @param   string  first row to select
+     *
+     * @return mixed   an MDB2_Result, a MDB2 error on failure
+     *
+     * @access  protected
+     */
+    function &_wrapResult($result, $types = array(), $result_class = true,
+        $result_wrap_class = false, $limit = null, $offset = null)
+    {
+        if ($types === true) {
+            if ($this->supports('result_introspection')) {
+                $this->loadModule('Reverse', null, true);
+                $tableInfo = $this->reverse->tableInfo($result);
+                if (PEAR::isError($tableInfo)) {
+                    return $tableInfo;
+                }
+                $types = array();
+                foreach ($tableInfo as $field) {
+                    $types[] = $field['mdb2type'];
+                }
+            } else {
+                $types = null;
+            }
+        }
+
+        if ($result_class === true) {
+            $result_class = $this->options['result_buffering']
+                ? $this->options['buffered_result_class'] : $this->options['result_class'];
+        }
+
+        if ($result_class) {
+            $class_name = sprintf($result_class, $this->phptype);
+            if (!MDB2::classExists($class_name)) {
+                $err =& $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                    'result class does not exist '.$class_name, __FUNCTION__);
+                return $err;
+            }
+            $result =& new $class_name($this, $result, $limit, $offset);
+            if (!MDB2::isResultCommon($result)) {
+                $err =& $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                    'result class is not extended from MDB2_Result_Common', __FUNCTION__);
+                return $err;
+            }
+            if (!empty($types)) {
+                $err = $result->setResultTypes($types);
+                if (PEAR::isError($err)) {
+                    $result->free();
+                    return $err;
+                }
+            }
+        }
+        if ($result_wrap_class === true) {
+            $result_wrap_class = $this->options['result_wrap_class'];
+        }
+        if ($result_wrap_class) {
+            if (!MDB2::classExists($result_wrap_class)) {
+                $err =& $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                    'result wrap class does not exist '.$result_wrap_class, __FUNCTION__);
+                return $err;
+            }
+            $result =& new $result_wrap_class($result, $this->fetchmode);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ function getServerVersion($native = false)
+
+    /**
+     * return version information about the server
+     *
+     * @param   bool    determines if the raw version string should be returned
+     *
+     * @return  mixed   array with version information or row string
+     *
+     * @access  public
+     */
+    function getServerVersion($native = false)
+    {
+        return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function setLimit($limit, $offset = null)
+
+    /**
+     * set the range of the next query
+     *
+     * @param   string  number of rows to select
+     * @param   string  first row to select
+     *
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function setLimit($limit, $offset = null)
+    {
+        if (!$this->supports('limit_queries')) {
+            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'limit is not supported by this driver', __FUNCTION__);
+        }
+        $limit = (int)$limit;
+        if ($limit < 0) {
+            return $this->raiseError(MDB2_ERROR_SYNTAX, null, null,
+                'it was not specified a valid selected range row limit', __FUNCTION__);
+        }
+        $this->limit = $limit;
+        if (!is_null($offset)) {
+            $offset = (int)$offset;
+            if ($offset < 0) {
+                return $this->raiseError(MDB2_ERROR_SYNTAX, null, null,
+                    'it was not specified a valid first selected range row', __FUNCTION__);
+            }
+            $this->offset = $offset;
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function subSelect($query, $type = false)
+
+    /**
+     * simple subselect emulation: leaves the query untouched for all RDBMS
+     * that support subselects
+     *
+     * @param   string  the SQL query for the subselect that may only
+     *                      return a column
+     * @param   string  determines type of the field
+     *
+     * @return  string  the query
+     *
+     * @access  public
+     */
+    function subSelect($query, $type = false)
+    {
+        if ($this->supports('sub_selects') === true) {
+            return $query;
+        }
+
+        if (!$this->supports('sub_selects')) {
+            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'method not implemented', __FUNCTION__);
+        }
+
+        $col = $this->queryCol($query, $type);
+        if (PEAR::isError($col)) {
+            return $col;
+        }
+        if (!is_array($col) || count($col) == 0) {
+            return 'NULL';
+        }
+        if ($type) {
+            $this->loadModule('Datatype', null, true);
+            return $this->datatype->implodeArray($col, $type);
+        }
+        return implode(', ', $col);
+    }
+
+    // }}}
+    // {{{ function replace($table, $fields)
+
+    /**
+     * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
+     * query, except that if there is already a row in the table with the same
+     * key field values, the REPLACE query just updates its values instead of
+     * inserting a new row.
+     *
+     * The REPLACE type of query does not make part of the SQL standards. Since
+     * practically only MySQL and SQLite implement it natively, this type of
+     * query isemulated through this method for other DBMS using standard types
+     * of queries inside a transaction to assure the atomicity of the operation.
+     *
+     * @param   string  name of the table on which the REPLACE query will
+     *       be executed.
+     * @param   array   associative array   that describes the fields and the
+     *       values that will be inserted or updated in the specified table. The
+     *       indexes of the array are the names of all the fields of the table.
+     *       The values of the array are also associative arrays that describe
+     *       the values and other properties of the table fields.
+     *
+     *       Here follows a list of field properties that need to be specified:
+     *
+     *       value
+     *           Value to be assigned to the specified field. This value may be
+     *           of specified in database independent type format as this
+     *           function can perform the necessary datatype conversions.
+     *
+     *           Default: this property is required unless the Null property is
+     *           set to 1.
+     *
+     *       type
+     *           Name of the type of the field. Currently, all types MDB2
+     *           are supported except for clob and blob.
+     *
+     *           Default: no type conversion
+     *
+     *       null
+     *           bool    property that indicates that the value for this field
+     *           should be set to null.
+     *
+     *           The default value for fields missing in INSERT queries may be
+     *           specified the definition of a table. Often, the default value
+     *           is already null, but since the REPLACE may be emulated using
+     *           an UPDATE query, make sure that all fields of the table are
+     *           listed in this function argument array.
+     *
+     *           Default: 0
+     *
+     *       key
+     *           bool    property that indicates that this field should be
+     *           handled as a primary key or at least as part of the compound
+     *           unique index of the table that will determine the row that will
+     *           updated if it exists or inserted a new row otherwise.
+     *
+     *           This function will fail if no key field is specified or if the
+     *           value of a key field is set to null because fields that are
+     *           part of unique index they may not be null.
+     *
+     *           Default: 0
+     *
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function replace($table, $fields)
+    {
+        if (!$this->supports('replace')) {
+            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'replace query is not supported', __FUNCTION__);
+        }
+        $count = count($fields);
+        $condition = $values = array();
+        for ($colnum = 0, reset($fields); $colnum < $count; next($fields), $colnum++) {
+            $name = key($fields);
+            if (isset($fields[$name]['null']) && $fields[$name]['null']) {
+                $value = 'NULL';
+            } else {
+                $type = isset($fields[$name]['type']) ? $fields[$name]['type'] : null;
+                $value = $this->quote($fields[$name]['value'], $type);
+            }
+            $values[$name] = $value;
+            if (isset($fields[$name]['key']) && $fields[$name]['key']) {
+                if ($value === 'NULL') {
+                    return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null,
+                        'key value '.$name.' may not be NULL', __FUNCTION__);
+                }
+                $condition[] = $name . '=' . $value;
+            }
+        }
+        if (empty($condition)) {
+            return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null,
+                'not specified which fields are keys', __FUNCTION__);
+        }
+
+        $result = null;
+        $in_transaction = $this->in_transaction;
+        if (!$in_transaction && PEAR::isError($result = $this->beginTransaction())) {
+            return $result;
+        }
+
+        $connection = $this->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+
+        $condition = ' WHERE '.implode(' AND ', $condition);
+        $query = "DELETE FROM $table$condition";
+        $result =& $this->_doQuery($query, true, $connection);
+        if (!PEAR::isError($result)) {
+            $affected_rows = $this->_affectedRows($connection, $result);
+            $insert = implode(', ', array_keys($values));
+            $values = implode(', ', $values);
+            $query = "INSERT INTO $table ($insert) VALUES ($values)";
+            $result =& $this->_doQuery($query, true, $connection);
+            if (!PEAR::isError($result)) {
+                $affected_rows += $this->_affectedRows($connection, $result);;
+            }
+        }
+
+        if (!$in_transaction) {
+            if (PEAR::isError($result)) {
+                $this->rollback();
+            } else {
+                $result = $this->commit();
+            }
+        }
+
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+
+        return $affected_rows;
+    }
+
+    // }}}
+    // {{{ function &prepare($query, $types = null, $result_types = null, $lobs = array())
+
+    /**
+     * Prepares a query for multiple execution with execute().
+     * With some database backends, this is emulated.
+     * prepare() requires a generic query as string like
+     * 'INSERT INTO numbers VALUES(?,?)' or
+     * 'INSERT INTO numbers VALUES(:foo,:bar)'.
+     * The ? and :[a-zA-Z] and  are placeholders which can be set using
+     * bindParam() and the query can be send off using the execute() method.
+     *
+     * @param   string  the query to prepare
+     * @param   mixed   array that contains the types of the placeholders
+     * @param   mixed   array that contains the types of the columns in
+     *                        the result set or MDB2_PREPARE_RESULT, if set to
+     *                        MDB2_PREPARE_MANIP the query is handled as a manipulation query
+     * @param   mixed   key (field) value (parameter) pair for all lob placeholders
+     *
+     * @return  mixed   resource handle for the prepared query on success, 
+     *                  a MDB2 error on failure
+     *
+     * @access  public
+     * @see     bindParam, execute
+     */
+    function &prepare($query, $types = null, $result_types = null, $lobs = array())
+    {
+        $is_manip = ($result_types === MDB2_PREPARE_MANIP);
+        $offset = $this->offset;
+        $limit = $this->limit;
+        $this->offset = $this->limit = 0;
+        $result = $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'pre'));
+        if ($result) {
+            if (PEAR::isError($result)) {
+                return $result;
+            }
+            $query = $result;
+        }
+        $placeholder_type_guess = $placeholder_type = null;
+        $question = '?';
+        $colon = ':';
+        $positions = array();
+        $position = 0;
+        $ignores = $this->sql_comments;
+        $ignores[] = $this->string_quoting;
+        $ignores[] = $this->identifier_quoting;
+        while ($position < strlen($query)) {
+            $q_position = strpos($query, $question, $position);
+            $c_position = strpos($query, $colon, $position);
+            if ($q_position && $c_position) {
+                $p_position = min($q_position, $c_position);
+            } elseif ($q_position) {
+                $p_position = $q_position;
+            } elseif ($c_position) {
+                $p_position = $c_position;
+            } else {
+                break;
+            }
+            if (is_null($placeholder_type)) {
+                $placeholder_type_guess = $query[$p_position];
+            }
+
+            $new_pos = $this->_skipDelimitedStrings($query, $position, $p_position);
+            if (PEAR::isError($new_pos)) {
+                return $new_pos;
+            }
+            if ($new_pos != $position) {
+                $position = $new_pos;
+                continue; //evaluate again starting from the new position
+            }
+
+            if ($query[$position] == $placeholder_type_guess) {
+                if (is_null($placeholder_type)) {
+                    $placeholder_type = $query[$p_position];
+                    $question = $colon = $placeholder_type;
+                    if (!empty($types) && is_array($types)) {
+                        if ($placeholder_type == ':') {
+                            if (is_int(key($types))) {
+                                $types_tmp = $types;
+                                $types = array();
+                                $count = -1;
+                            }
+                        } else {
+                            $types = array_values($types);
+                        }
+                    }
+                }
+                if ($placeholder_type == ':') {
+                    $parameter = preg_replace('/^.{'.($position+1).'}([a-z0-9_]+).*$/si', '\\1', $query);
+                    if ($parameter === '') {
+                        $err =& $this->raiseError(MDB2_ERROR_SYNTAX, null, null,
+                            'named parameter with an empty name', __FUNCTION__);
+                        return $err;
+                    }
+                    $positions[$p_position] = $parameter;
+                    $query = substr_replace($query, '?', $position, strlen($parameter)+1);
+                    // use parameter name in type array
+                    if (isset($count) && isset($types_tmp[++$count])) {
+                        $types[$parameter] = $types_tmp[$count];
+                    }
+                } else {
+                    $positions[$p_position] = count($positions);
+                }
+                $position = $p_position + 1;
+            } else {
+                $position = $p_position;
+            }
+        }
+        $class_name = 'MDB2_Statement_'.$this->phptype;
+        $statement = null;
+        $obj =& new $class_name($this, $statement, $positions, $query, $types, $result_types, $is_manip, $limit, $offset);
+        $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'post', 'result' => $obj));
+        return $obj;
+    }
+
+    // }}}
+    // {{{ function _skipDelimitedStrings($query, $position, $p_position)
+    
+    /**
+     * Utility method, used by prepare() to avoid replacing placeholders within delimited strings.
+     * Check if the placeholder is contained within a delimited string.
+     * If so, skip it and advance the position, otherwise return the current position,
+     * which is valid
+     *
+     * @param string $query
+     * @param integer $position current string cursor position
+     * @param integer $p_position placeholder position
+     *
+     * @return mixed integer $new_position on success
+     *               MDB2_Error on failure
+     *
+     * @access  protected
+     */
+    function _skipDelimitedStrings($query, $position, $p_position)
+    {
+        $ignores = $this->sql_comments;
+        $ignores[] = $this->string_quoting;
+        $ignores[] = $this->identifier_quoting;
+        
+        foreach ($ignores as $ignore) {
+            if (!empty($ignore['start'])) {
+                if (is_int($start_quote = strpos($query, $ignore['start'], $position)) && $start_quote < $p_position) {
+                    $end_quote = $start_quote;
+                    do {
+                        if (!is_int($end_quote = strpos($query, $ignore['end'], $end_quote + 1))) {
+                            if ($ignore['end'] === "\n") {
+                                $end_quote = strlen($query) - 1;
+                            } else {
+                                $err =& $this->raiseError(MDB2_ERROR_SYNTAX, null, null,
+                                    'query with an unterminated text string specified', __FUNCTION__);
+                                return $err;
+                            }
+                        }
+                    } while ($ignore['escape'] && $query[($end_quote - 1)] == $ignore['escape']);
+                    $position = $end_quote + 1;
+                    return $position;
+                }
+            }
+        }
+        return $position;
+    }
+    
+    // }}}
+    // {{{ function quote($value, $type = null, $quote = true)
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param   string  text string value that is intended to be converted.
+     * @param   string  type to which the value should be converted to
+     * @param   bool    quote
+     * @param   bool    escape wildcards
+     *
+     * @return  string  text string that represents the given argument value in
+     *       a DBMS specific format.
+     *
+     * @access  public
+     */
+    function quote($value, $type = null, $quote = true, $escape_wildcards = false)
+    {
+        $result = $this->loadModule('Datatype', null, true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+
+        return $this->datatype->quote($value, $type, $quote, $escape_wildcards);
+    }
+
+    // }}}
+    // {{{ function getDeclaration($type, $name, $field)
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare
+     * of the given type
+     *
+     * @param   string  type to which the value should be converted to
+     * @param   string  name the field to be declared.
+     * @param   string  definition of the field
+     *
+     * @return  string  DBMS specific SQL code portion that should be used to
+     *                 declare the specified field.
+     *
+     * @access  public
+     */
+    function getDeclaration($type, $name, $field)
+    {
+        $result = $this->loadModule('Datatype', null, true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        return $this->datatype->getDeclaration($type, $name, $field);
+    }
+
+    // }}}
+    // {{{ function compareDefinition($current, $previous)
+
+    /**
+     * Obtain an array of changes that may need to applied
+     *
+     * @param   array   new definition
+     * @param   array   old definition
+     *
+     * @return  array   containing all changes that will need to be applied
+     *
+     * @access  public
+     */
+    function compareDefinition($current, $previous)
+    {
+        $result = $this->loadModule('Datatype', null, true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        return $this->datatype->compareDefinition($current, $previous);
+    }
+
+    // }}}
+    // {{{ function supports($feature)
+
+    /**
+     * Tell whether a DB implementation or its backend extension
+     * supports a given feature.
+     *
+     * @param   string  name of the feature (see the MDB2 class doc)
+     *
+     * @return  bool|string if this DB implementation supports a given feature
+     *                      false means no, true means native,
+     *                      'emulated' means emulated
+     *
+     * @access  public
+     */
+    function supports($feature)
+    {
+        if (array_key_exists($feature, $this->supported)) {
+            return $this->supported[$feature];
+        }
+        return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            "unknown support feature $feature", __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function getSequenceName($sqn)
+
+    /**
+     * adds sequence name formatting to a sequence name
+     *
+     * @param   string  name of the sequence
+     *
+     * @return  string  formatted sequence name
+     *
+     * @access  public
+     */
+    function getSequenceName($sqn)
+    {
+        return sprintf($this->options['seqname_format'],
+            preg_replace('/[^a-z0-9_\$.]/i', '_', $sqn));
+    }
+
+    // }}}
+    // {{{ function getIndexName($idx)
+
+    /**
+     * adds index name formatting to a index name
+     *
+     * @param   string  name of the index
+     *
+     * @return  string  formatted index name
+     *
+     * @access  public
+     */
+    function getIndexName($idx)
+    {
+        return sprintf($this->options['idxname_format'],
+            preg_replace('/[^a-z0-9_\$]/i', '_', $idx));
+    }
+
+    // }}}
+    // {{{ function nextID($seq_name, $ondemand = true)
+
+    /**
+     * Returns the next free id of a sequence
+     *
+     * @param   string  name of the sequence
+     * @param   bool    when true missing sequences are automatic created
+     *
+     * @return  mixed   MDB2 Error Object or id
+     *
+     * @access  public
+     */
+    function nextID($seq_name, $ondemand = true)
+    {
+        return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function lastInsertID($table = null, $field = null)
+
+    /**
+     * Returns the autoincrement ID if supported or $id or fetches the current
+     * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
+     *
+     * @param   string  name of the table into which a new row was inserted
+     * @param   string  name of the field into which a new row was inserted
+     *
+     * @return  mixed   MDB2 Error Object or id
+     *
+     * @access  public
+     */
+    function lastInsertID($table = null, $field = null)
+    {
+        return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function currID($seq_name)
+
+    /**
+     * Returns the current id of a sequence
+     *
+     * @param   string  name of the sequence
+     *
+     * @return  mixed   MDB2 Error Object or id
+     *
+     * @access  public
+     */
+    function currID($seq_name)
+    {
+        $this->warnings[] = 'database does not support getting current
+            sequence value, the sequence value was incremented';
+        return $this->nextID($seq_name);
+    }
+
+    // }}}
+    // {{{ function queryOne($query, $type = null, $colnum = 0)
+
+    /**
+     * Execute the specified query, fetch the value from the first column of
+     * the first row of the result set and then frees
+     * the result set.
+     *
+     * @param   string  the SELECT query statement to be executed.
+     * @param   string  optional argument that specifies the expected
+     *       datatype of the result set field, so that an eventual conversion
+     *       may be performed. The default datatype is text, meaning that no
+     *       conversion is performed
+     * @param   int     the column number to fetch
+     *
+     * @return  mixed   MDB2_OK or field value on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function queryOne($query, $type = null, $colnum = 0)
+    {
+        $result = $this->query($query, $type);
+        if (!MDB2::isResultCommon($result)) {
+            return $result;
+        }
+
+        $one = $result->fetchOne($colnum);
+        $result->free();
+        return $one;
+    }
+
+    // }}}
+    // {{{ function queryRow($query, $types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT)
+
+    /**
+     * Execute the specified query, fetch the values from the first
+     * row of the result set into an array and then frees
+     * the result set.
+     *
+     * @param   string  the SELECT query statement to be executed.
+     * @param   array   optional array argument that specifies a list of
+     *       expected datatypes of the result set columns, so that the eventual
+     *       conversions may be performed. The default list of datatypes is
+     *       empty, meaning that no conversion is performed.
+     * @param   int     how the array data should be indexed
+     *
+     * @return  mixed   MDB2_OK or data array on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function queryRow($query, $types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT)
+    {
+        $result = $this->query($query, $types);
+        if (!MDB2::isResultCommon($result)) {
+            return $result;
+        }
+
+        $row = $result->fetchRow($fetchmode);
+        $result->free();
+        return $row;
+    }
+
+    // }}}
+    // {{{ function queryCol($query, $type = null, $colnum = 0)
+
+    /**
+     * Execute the specified query, fetch the value from the first column of
+     * each row of the result set into an array and then frees the result set.
+     *
+     * @param   string  the SELECT query statement to be executed.
+     * @param   string  optional argument that specifies the expected
+     *       datatype of the result set field, so that an eventual conversion
+     *       may be performed. The default datatype is text, meaning that no
+     *       conversion is performed
+     * @param   int     the row number to fetch
+     *
+     * @return  mixed   MDB2_OK or data array on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function queryCol($query, $type = null, $colnum = 0)
+    {
+        $result = $this->query($query, $type);
+        if (!MDB2::isResultCommon($result)) {
+            return $result;
+        }
+
+        $col = $result->fetchCol($colnum);
+        $result->free();
+        return $col;
+    }
+
+    // }}}
+    // {{{ function queryAll($query, $types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT, $rekey = false, $force_array = false, $group = false)
+
+    /**
+     * Execute the specified query, fetch all the rows of the result set into
+     * a two dimensional array and then frees the result set.
+     *
+     * @param   string  the SELECT query statement to be executed.
+     * @param   array   optional array argument that specifies a list of
+     *       expected datatypes of the result set columns, so that the eventual
+     *       conversions may be performed. The default list of datatypes is
+     *       empty, meaning that no conversion is performed.
+     * @param   int     how the array data should be indexed
+     * @param   bool    if set to true, the $all will have the first
+     *       column as its first dimension
+     * @param   bool    used only when the query returns exactly
+     *       two columns. If true, the values of the returned array will be
+     *       one-element arrays instead of scalars.
+     * @param   bool    if true, the values of the returned array is
+     *       wrapped in another array.  If the same key value (in the first
+     *       column) repeats itself, the values will be appended to this array
+     *       instead of overwriting the existing values.
+     *
+     * @return  mixed   MDB2_OK or data array on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function queryAll($query, $types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT,
+        $rekey = false, $force_array = false, $group = false)
+    {
+        $result = $this->query($query, $types);
+        if (!MDB2::isResultCommon($result)) {
+            return $result;
+        }
+
+        $all = $result->fetchAll($fetchmode, $rekey, $force_array, $group);
+        $result->free();
+        return $all;
+    }
+
+    // }}}
+}
+
+// }}}
+// {{{ class MDB2_Result
+
+/**
+ * The dummy class that all user space result classes should extend from
+ *
+ * @package     MDB2
+ * @category    Database
+ * @author      Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Result
+{
+}
+
+// }}}
+// {{{ class MDB2_Result_Common extends MDB2_Result
+
+/**
+ * The common result class for MDB2 result objects
+ *
+ * @package     MDB2
+ * @category    Database
+ * @author      Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Result_Common extends MDB2_Result
+{
+    // {{{ Variables (Properties)
+
+    var $db;
+    var $result;
+    var $rownum = -1;
+    var $types = array();
+    var $values = array();
+    var $offset;
+    var $offset_count = 0;
+    var $limit;
+    var $column_names;
+
+    // }}}
+    // {{{ constructor: function __construct(&$db, &$result, $limit = 0, $offset = 0)
+
+    /**
+     * Constructor
+     */
+    function __construct(&$db, &$result, $limit = 0, $offset = 0)
+    {
+        $this->db =& $db;
+        $this->result =& $result;
+        $this->offset = $offset;
+        $this->limit = max(0, $limit - 1);
+    }
+
+    // }}}
+    // {{{ function MDB2_Result_Common(&$db, &$result, $limit = 0, $offset = 0)
+
+    /**
+     * PHP 4 Constructor
+     */
+    function MDB2_Result_Common(&$db, &$result, $limit = 0, $offset = 0)
+    {
+        $this->__construct($db, $result, $limit, $offset);
+    }
+
+    // }}}
+    // {{{ function setResultTypes($types)
+
+    /**
+     * Define the list of types to be associated with the columns of a given
+     * result set.
+     *
+     * This function may be called before invoking fetchRow(), fetchOne(),
+     * fetchCol() and fetchAll() so that the necessary data type
+     * conversions are performed on the data to be retrieved by them. If this
+     * function is not called, the type of all result set columns is assumed
+     * to be text, thus leading to not perform any conversions.
+     *
+     * @param   array   variable that lists the
+     *       data types to be expected in the result set columns. If this array
+     *       contains less types than the number of columns that are returned
+     *       in the result set, the remaining columns are assumed to be of the
+     *       type text. Currently, the types clob and blob are not fully
+     *       supported.
+     *
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function setResultTypes($types)
+    {
+        $load = $this->db->loadModule('Datatype', null, true);
+        if (PEAR::isError($load)) {
+            return $load;
+        }
+        $types = $this->db->datatype->checkResultTypes($types);
+        if (PEAR::isError($types)) {
+            return $types;
+        }
+        $this->types = $types;
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function seek($rownum = 0)
+
+    /**
+     * Seek to a specific row in a result set
+     *
+     * @param   int     number of the row where the data can be found
+     *
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function seek($rownum = 0)
+    {
+        $target_rownum = $rownum - 1;
+        if ($this->rownum > $target_rownum) {
+            return $this->db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'seeking to previous rows not implemented', __FUNCTION__);
+        }
+        while ($this->rownum < $target_rownum) {
+            $this->fetchRow();
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)
+
+    /**
+     * Fetch and return a row of data
+     *
+     * @param   int     how the array data should be indexed
+     * @param   int     number of the row where the data can be found
+     *
+     * @return  int     data array on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)
+    {
+        $err =& $this->db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+        return $err;
+    }
+
+    // }}}
+    // {{{ function fetchOne($colnum = 0)
+
+    /**
+     * fetch single column from the next row from a result set
+     *
+     * @param   int     the column number to fetch
+     * @param   int     number of the row where the data can be found
+     *
+     * @return  string  data on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function fetchOne($colnum = 0, $rownum = null)
+    {
+        $fetchmode = is_numeric($colnum) ? MDB2_FETCHMODE_ORDERED : MDB2_FETCHMODE_ASSOC;
+        $row = $this->fetchRow($fetchmode, $rownum);
+        if (!is_array($row) || PEAR::isError($row)) {
+            return $row;
+        }
+        if (!array_key_exists($colnum, $row)) {
+            return $this->db->raiseError(MDB2_ERROR_TRUNCATED, null, null,
+                'column is not defined in the result set: '.$colnum, __FUNCTION__);
+        }
+        return $row[$colnum];
+    }
+
+    // }}}
+    // {{{ function fetchCol($colnum = 0)
+
+    /**
+     * Fetch and return a column from the current row pointer position
+     *
+     * @param   int     the column number to fetch
+     *
+     * @return  mixed   data array on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function fetchCol($colnum = 0)
+    {
+        $column = array();
+        $fetchmode = is_numeric($colnum) ? MDB2_FETCHMODE_ORDERED : MDB2_FETCHMODE_ASSOC;
+        $row = $this->fetchRow($fetchmode);
+        if (is_array($row)) {
+            if (!array_key_exists($colnum, $row)) {
+                return $this->db->raiseError(MDB2_ERROR_TRUNCATED, null, null,
+                    'column is not defined in the result set: '.$colnum, __FUNCTION__);
+            }
+            do {
+                $column[] = $row[$colnum];
+            } while (is_array($row = $this->fetchRow($fetchmode)));
+        }
+        if (PEAR::isError($row)) {
+            return $row;
+        }
+        return $column;
+    }
+
+    // }}}
+    // {{{ function fetchAll($fetchmode = MDB2_FETCHMODE_DEFAULT, $rekey = false, $force_array = false, $group = false)
+
+    /**
+     * Fetch and return all rows from the current row pointer position
+     *
+     * @param   int     $fetchmode  the fetch mode to use:
+     *                            + MDB2_FETCHMODE_ORDERED
+     *                            + MDB2_FETCHMODE_ASSOC
+     *                            + MDB2_FETCHMODE_ORDERED | MDB2_FETCHMODE_FLIPPED
+     *                            + MDB2_FETCHMODE_ASSOC | MDB2_FETCHMODE_FLIPPED
+     * @param   bool    if set to true, the $all will have the first
+     *       column as its first dimension
+     * @param   bool    used only when the query returns exactly
+     *       two columns. If true, the values of the returned array will be
+     *       one-element arrays instead of scalars.
+     * @param   bool    if true, the values of the returned array is
+     *       wrapped in another array.  If the same key value (in the first
+     *       column) repeats itself, the values will be appended to this array
+     *       instead of overwriting the existing values.
+     *
+     * @return  mixed   data array on success, a MDB2 error on failure
+     *
+     * @access  public
+     * @see     getAssoc()
+     */
+    function fetchAll($fetchmode = MDB2_FETCHMODE_DEFAULT, $rekey = false,
+        $force_array = false, $group = false)
+    {
+        $all = array();
+        $row = $this->fetchRow($fetchmode);
+        if (PEAR::isError($row)) {
+            return $row;
+        } elseif (!$row) {
+            return $all;
+        }
+
+        $shift_array = $rekey ? false : null;
+        if (!is_null($shift_array)) {
+            if (is_object($row)) {
+                $colnum = count(get_object_vars($row));
+            } else {
+                $colnum = count($row);
+            }
+            if ($colnum < 2) {
+                return $this->db->raiseError(MDB2_ERROR_TRUNCATED, null, null,
+                    'rekey feature requires atleast 2 column', __FUNCTION__);
+            }
+            $shift_array = (!$force_array && $colnum == 2);
+        }
+
+        if ($rekey) {
+            do {
+                if (is_object($row)) {
+                    $arr = get_object_vars($row);
+                    $key = reset($arr);
+                    unset($row->{$key});
+                } else {
+                    if ($fetchmode & MDB2_FETCHMODE_ASSOC) {
+                        $key = reset($row);
+                        unset($row[key($row)]);
+                    } else {
+                        $key = array_shift($row);
+                    }
+                    if ($shift_array) {
+                        $row = array_shift($row);
+                    }
+                }
+                if ($group) {
+                    $all[$key][] = $row;
+                } else {
+                    $all[$key] = $row;
+                }
+            } while (($row = $this->fetchRow($fetchmode)));
+        } elseif ($fetchmode & MDB2_FETCHMODE_FLIPPED) {
+            do {
+                foreach ($row as $key => $val) {
+                    $all[$key][] = $val;
+                }
+            } while (($row = $this->fetchRow($fetchmode)));
+        } else {
+            do {
+                $all[] = $row;
+            } while (($row = $this->fetchRow($fetchmode)));
+        }
+
+        return $all;
+    }
+
+    // }}}
+    // {{{ function rowCount()
+    /**
+     * Returns the actual row number that was last fetched (count from 0)
+     * @return  int
+     *
+     * @access  public
+     */
+    function rowCount()
+    {
+        return $this->rownum + 1;
+    }
+
+    // }}}
+    // {{{ function numRows()
+
+    /**
+     * Returns the number of rows in a result object
+     *
+     * @return  mixed   MDB2 Error Object or the number of rows
+     *
+     * @access  public
+     */
+    function numRows()
+    {
+        return $this->db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function nextResult()
+
+    /**
+     * Move the internal result pointer to the next available result
+     *
+     * @return  true on success, false if there is no more result set or an error object on failure
+     *
+     * @access  public
+     */
+    function nextResult()
+    {
+        return $this->db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function getColumnNames()
+
+    /**
+     * Retrieve the names of columns returned by the DBMS in a query result or
+     * from the cache.
+     *
+     * @param   bool    If set to true the values are the column names,
+     *                  otherwise the names of the columns are the keys.
+     * @return  mixed   Array variable that holds the names of columns or an
+     *                  MDB2 error on failure.
+     *                  Some DBMS may not return any columns when the result set
+     *                  does not contain any rows.
+     *
+     * @access  public
+     */
+    function getColumnNames($flip = false)
+    {
+        if (!isset($this->column_names)) {
+            $result = $this->_getColumnNames();
+            if (PEAR::isError($result)) {
+                return $result;
+            }
+            $this->column_names = $result;
+        }
+        if ($flip) {
+            return array_flip($this->column_names);
+        }
+        return $this->column_names;
+    }
+
+    // }}}
+    // {{{ function _getColumnNames()
+
+    /**
+     * Retrieve the names of columns returned by the DBMS in a query result.
+     *
+     * @return  mixed   Array variable that holds the names of columns as keys
+     *                  or an MDB2 error on failure.
+     *                  Some DBMS may not return any columns when the result set
+     *                  does not contain any rows.
+     *
+     * @access  private
+     */
+    function _getColumnNames()
+    {
+        return $this->db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function numCols()
+
+    /**
+     * Count the number of columns returned by the DBMS in a query result.
+     *
+     * @return  mixed   integer value with the number of columns, a MDB2 error
+     *       on failure
+     *
+     * @access  public
+     */
+    function numCols()
+    {
+        return $this->db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ function getResource()
+
+    /**
+     * return the resource associated with the result object
+     *
+     * @return  resource
+     *
+     * @access  public
+     */
+    function getResource()
+    {
+        return $this->result;
+    }
+
+    // }}}
+    // {{{ function bindColumn($column, &$value, $type = null)
+
+    /**
+     * Set bind variable to a column.
+     *
+     * @param   int     column number or name
+     * @param   mixed   variable reference
+     * @param   string  specifies the type of the field
+     *
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function bindColumn($column, &$value, $type = null)
+    {
+        if (!is_numeric($column)) {
+            $column_names = $this->getColumnNames();
+            if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+                if ($this->db->options['field_case'] == CASE_LOWER) {
+                    $column = strtolower($column);
+                } else {
+                    $column = strtoupper($column);
+                }
+            }
+            $column = $column_names[$column];
+        }
+        $this->values[$column] =& $value;
+        if (!is_null($type)) {
+            $this->types[$column] = $type;
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function _assignBindColumns($row)
+
+    /**
+     * Bind a variable to a value in the result row.
+     *
+     * @param   array   row data
+     *
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  private
+     */
+    function _assignBindColumns($row)
+    {
+        $row = array_values($row);
+        foreach ($row as $column => $value) {
+            if (array_key_exists($column, $this->values)) {
+                $this->values[$column] = $value;
+            }
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function free()
+
+    /**
+     * Free the internal resources associated with result.
+     *
+     * @return  bool    true on success, false if result is invalid
+     *
+     * @access  public
+     */
+    function free()
+    {
+        $this->result = false;
+        return MDB2_OK;
+    }
+
+    // }}}
+}
+
+// }}}
+// {{{ class MDB2_Row
+
+/**
+ * The simple class that accepts row data as an array
+ *
+ * @package     MDB2
+ * @category    Database
+ * @author      Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Row
+{
+    // {{{ constructor: function __construct(&$row)
+
+    /**
+     * constructor
+     *
+     * @param   resource    row data as array
+     */
+    function __construct(&$row)
+    {
+        foreach ($row as $key => $value) {
+            $this->$key = &$row[$key];
+        }
+    }
+
+    // }}}
+    // {{{ function MDB2_Row(&$row)
+
+    /**
+     * PHP 4 Constructor
+     *
+     * @param   resource    row data as array
+     */
+    function MDB2_Row(&$row)
+    {
+        $this->__construct($row);
+    }
+
+    // }}}
+}
+
+// }}}
+// {{{ class MDB2_Statement_Common
+
+/**
+ * The common statement class for MDB2 statement objects
+ *
+ * @package     MDB2
+ * @category    Database
+ * @author      Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Statement_Common
+{
+    // {{{ Variables (Properties)
+
+    var $db;
+    var $statement;
+    var $query;
+    var $result_types;
+    var $types;
+    var $values = array();
+    var $limit;
+    var $offset;
+    var $is_manip;
+
+    // }}}
+    // {{{ constructor: function __construct(&$db, &$statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null)
+
+    /**
+     * Constructor
+     */
+    function __construct(&$db, &$statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null)
+    {
+        $this->db =& $db;
+        $this->statement =& $statement;
+        $this->positions = $positions;
+        $this->query = $query;
+        $this->types = (array)$types;
+        $this->result_types = (array)$result_types;
+        $this->limit = $limit;
+        $this->is_manip = $is_manip;
+        $this->offset = $offset;
+    }
+
+    // }}}
+    // {{{ function MDB2_Statement_Common(&$db, &$statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null)
+
+    /**
+     * PHP 4 Constructor
+     */
+    function MDB2_Statement_Common(&$db, &$statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null)
+    {
+        $this->__construct($db, $statement, $positions, $query, $types, $result_types, $is_manip, $limit, $offset);
+    }
+
+    // }}}
+    // {{{ function bindValue($parameter, &$value, $type = null)
+
+    /**
+     * Set the value of a parameter of a prepared query.
+     *
+     * @param   int     the order number of the parameter in the query
+     *       statement. The order number of the first parameter is 1.
+     * @param   mixed   value that is meant to be assigned to specified
+     *       parameter. The type of the value depends on the $type argument.
+     * @param   string  specifies the type of the field
+     *
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function bindValue($parameter, $value, $type = null)
+    {
+        if (!is_numeric($parameter)) {
+            $parameter = preg_replace('/^:(.*)$/', '\\1', $parameter);
+        }
+        if (!in_array($parameter, $this->positions)) {
+            return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__);
+        }
+        $this->values[$parameter] = $value;
+        if (!is_null($type)) {
+            $this->types[$parameter] = $type;
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function bindValueArray($values, $types = null)
+
+    /**
+     * Set the values of multiple a parameter of a prepared query in bulk.
+     *
+     * @param   array   specifies all necessary information
+     *       for bindValue() the array elements must use keys corresponding to
+     *       the number of the position of the parameter.
+     * @param   array   specifies the types of the fields
+     *
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     * @see     bindParam()
+     */
+    function bindValueArray($values, $types = null)
+    {
+        $types = is_array($types) ? array_values($types) : array_fill(0, count($values), null);
+        $parameters = array_keys($values);
+        foreach ($parameters as $key => $parameter) {
+            $err = $this->bindValue($parameter, $values[$parameter], $types[$key]);
+            if (PEAR::isError($err)) {
+                return $err;
+            }
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function bindParam($parameter, &$value, $type = null)
+
+    /**
+     * Bind a variable to a parameter of a prepared query.
+     *
+     * @param   int     the order number of the parameter in the query
+     *       statement. The order number of the first parameter is 1.
+     * @param   mixed   variable that is meant to be bound to specified
+     *       parameter. The type of the value depends on the $type argument.
+     * @param   string  specifies the type of the field
+     *
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function bindParam($parameter, &$value, $type = null)
+    {
+        if (!is_numeric($parameter)) {
+            $parameter = preg_replace('/^:(.*)$/', '\\1', $parameter);
+        }
+        if (!in_array($parameter, $this->positions)) {
+            return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__);
+        }
+        $this->values[$parameter] =& $value;
+        if (!is_null($type)) {
+            $this->types[$parameter] = $type;
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function bindParamArray(&$values, $types = null)
+
+    /**
+     * Bind the variables of multiple a parameter of a prepared query in bulk.
+     *
+     * @param   array   specifies all necessary information
+     *       for bindParam() the array elements must use keys corresponding to
+     *       the number of the position of the parameter.
+     * @param   array   specifies the types of the fields
+     *
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     * @see     bindParam()
+     */
+    function bindParamArray(&$values, $types = null)
+    {
+        $types = is_array($types) ? array_values($types) : array_fill(0, count($values), null);
+        $parameters = array_keys($values);
+        foreach ($parameters as $key => $parameter) {
+            $err = $this->bindParam($parameter, $values[$parameter], $types[$key]);
+            if (PEAR::isError($err)) {
+                return $err;
+            }
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function &execute($values = null, $result_class = true, $result_wrap_class = false)
+
+    /**
+     * Execute a prepared query statement.
+     *
+     * @param   array   specifies all necessary information
+     *       for bindParam() the array elements must use keys corresponding to
+     *       the number of the position of the parameter.
+     * @param   mixed   specifies which result class to use
+     * @param   mixed   specifies which class to wrap results in
+     *
+     * @return  mixed   a result handle or MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function &execute($values = null, $result_class = true, $result_wrap_class = false)
+    {
+        if (is_null($this->positions)) {
+            return $this->db->raiseError(MDB2_ERROR, null, null,
+                'Prepared statement has already been freed', __FUNCTION__);
+        }
+
+        $values = (array)$values;
+        if (!empty($values)) {
+            $err = $this->bindValueArray($values);
+            if (PEAR::isError($err)) {
+                return $this->db->raiseError(MDB2_ERROR, null, null,
+                                            'Binding Values failed with message: ' . $err->getMessage(), __FUNCTION__);
+            }
+        }
+        $result =& $this->_execute($result_class, $result_wrap_class);
+        return $result;
+    }
+
+    // }}}
+    // {{{ function &_execute($result_class = true, $result_wrap_class = false)
+
+    /**
+     * Execute a prepared query statement helper method.
+     *
+     * @param   mixed   specifies which result class to use
+     * @param   mixed   specifies which class to wrap results in
+     *
+     * @return  mixed   MDB2_Result or integer on success, a MDB2 error on failure
+     *
+     * @access  private
+     */
+    function &_execute($result_class = true, $result_wrap_class = false)
+    {
+        $this->last_query = $this->query;
+        $query = '';
+        $last_position = 0;
+        foreach ($this->positions as $current_position => $parameter) {
+            if (!array_key_exists($parameter, $this->values)) {
+                return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                    'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__);
+            }
+            $value = $this->values[$parameter];
+            $query.= substr($this->query, $last_position, $current_position - $last_position);
+            if (!isset($value)) {
+                $value_quoted = 'NULL';
+            } else {
+                $type = !empty($this->types[$parameter]) ? $this->types[$parameter] : null;
+                $value_quoted = $this->db->quote($value, $type);
+                if (PEAR::isError($value_quoted)) {
+                    return $value_quoted;
+                }
+            }
+            $query.= $value_quoted;
+            $last_position = $current_position + 1;
+        }
+        $query.= substr($this->query, $last_position);
+
+        $this->db->offset = $this->offset;
+        $this->db->limit = $this->limit;
+        if ($this->is_manip) {
+            $result = $this->db->exec($query);
+        } else {
+            $result =& $this->db->query($query, $this->result_types, $result_class, $result_wrap_class);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ function free()
+
+    /**
+     * Release resources allocated for the specified prepared query.
+     *
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function free()
+    {
+        if (is_null($this->positions)) {
+            return $this->db->raiseError(MDB2_ERROR, null, null,
+                'Prepared statement has already been freed', __FUNCTION__);
+        }
+
+        $this->statement = null;
+        $this->positions = null;
+        $this->query = null;
+        $this->types = null;
+        $this->result_types = null;
+        $this->limit = null;
+        $this->is_manip = null;
+        $this->offset = null;
+        $this->values = null;
+
+        return MDB2_OK;
+    }
+
+    // }}}
+}
+
+// }}}
+// {{{ class MDB2_Module_Common
+
+/**
+ * The common modules class for MDB2 module objects
+ *
+ * @package     MDB2
+ * @category    Database
+ * @author      Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Module_Common
+{
+    // {{{ Variables (Properties)
+
+    /**
+     * contains the key to the global MDB2 instance array of the associated
+     * MDB2 instance
+     *
+     * @var     int
+     * @access  protected
+     */
+    var $db_index;
+
+    // }}}
+    // {{{ constructor: function __construct($db_index)
+
+    /**
+     * Constructor
+     */
+    function __construct($db_index)
+    {
+        $this->db_index = $db_index;
+    }
+
+    // }}}
+    // {{{ function MDB2_Module_Common($db_index)
+
+    /**
+     * PHP 4 Constructor
+     */
+    function MDB2_Module_Common($db_index)
+    {
+        $this->__construct($db_index);
+    }
+
+    // }}}
+    // {{{ function &getDBInstance()
+
+    /**
+     * Get the instance of MDB2 associated with the module instance
+     *
+     * @return  object  MDB2 instance or a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function &getDBInstance()
+    {
+        if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
+            $result =& $GLOBALS['_MDB2_databases'][$this->db_index];
+        } else {
+            $result =& MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'could not find MDB2 instance');
+        }
+        return $result;
+    }
+
+    // }}}
+}
+
+// }}}
+// {{{ function MDB2_closeOpenTransactions()
+
+/**
+ * Close any open transactions form persistent connections
+ *
+ * @return  void
+ *
+ * @access  public
+ */
+
+function MDB2_closeOpenTransactions()
+{
+    reset($GLOBALS['_MDB2_databases']);
+    while (next($GLOBALS['_MDB2_databases'])) {
+        $key = key($GLOBALS['_MDB2_databases']);
+        if ($GLOBALS['_MDB2_databases'][$key]->opened_persistent
+            && $GLOBALS['_MDB2_databases'][$key]->in_transaction
+        ) {
+            $GLOBALS['_MDB2_databases'][$key]->rollback();
+        }
+    }
+}
+
+// }}}
+// {{{ function MDB2_defaultDebugOutput(&$db, $scope, $message, $is_manip = null)
+
+/**
+ * default debug output handler
+ *
+ * @param   object  reference to an MDB2 database object
+ * @param   string  usually the method name that triggered the debug call:
+ *                  for example 'query', 'prepare', 'execute', 'parameters',
+ *                  'beginTransaction', 'commit', 'rollback'
+ * @param   string  message that should be appended to the debug variable
+ * @param   array   contains context information about the debug() call
+ *                  common keys are: is_manip, time, result etc.
+ *
+ * @return  void|string optionally return a modified message, this allows
+ *                      rewriting a query before being issued or prepared
+ *
+ * @access  public
+ */
+function MDB2_defaultDebugOutput(&$db, $scope, $message, $context = array())
+{
+    $db->debug_output.= $scope.'('.$db->db_index.'): ';
+    $db->debug_output.= $message.$db->getOption('log_line_break');
+    return $message;
+}
+
+// }}}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Date.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Date.php
new file mode 100644 (file)
index 0000000..ce84654
--- /dev/null
@@ -0,0 +1,183 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: Date.php,v 1.10 2006/03/01 12:15:32 lsmith Exp $
+//
+
+/**
+ * @package  MDB2
+ * @category Database
+ * @author   Lukas Smith <smith@pooteeweet.org>
+ */
+
+/**
+ * Several methods to convert the MDB2 native timestamp format (ISO based)
+ * to and from data structures that are convenient to worth with in side of php.
+ * For more complex date arithmetic please take a look at the Date package in PEAR
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Date
+{
+    // {{{ mdbNow()
+
+    /**
+     * return the current datetime
+     *
+     * @return string current datetime in the MDB2 format
+     * @access public
+     */
+    function mdbNow()
+    {
+        return date('Y-m-d H:i:s');
+    }
+    // }}}
+
+    // {{{ mdbToday()
+
+    /**
+     * return the current date
+     *
+     * @return string current date in the MDB2 format
+     * @access public
+     */
+    function mdbToday()
+    {
+        return date('Y-m-d');
+    }
+    // }}}
+
+    // {{{ mdbTime()
+
+    /**
+     * return the current time
+     *
+     * @return string current time in the MDB2 format
+     * @access public
+     */
+    function mdbTime()
+    {
+        return date('H:i:s');
+    }
+    // }}}
+
+    // {{{ date2Mdbstamp()
+
+    /**
+     * convert a date into a MDB2 timestamp
+     *
+     * @param int hour of the date
+     * @param int minute of the date
+     * @param int second of the date
+     * @param int month of the date
+     * @param int day of the date
+     * @param int year of the date
+     *
+     * @return string a valid MDB2 timestamp
+     * @access public
+     */
+    function date2Mdbstamp($hour = null, $minute = null, $second = null,
+        $month = null, $day = null, $year = null)
+    {
+        return MDB2_Date::unix2Mdbstamp(mktime($hour, $minute, $second, $month, $day, $year, -1));
+    }
+    // }}}
+
+    // {{{ unix2Mdbstamp()
+
+    /**
+     * convert a unix timestamp into a MDB2 timestamp
+     *
+     * @param int a valid unix timestamp
+     *
+     * @return string a valid MDB2 timestamp
+     * @access public
+     */
+    function unix2Mdbstamp($unix_timestamp)
+    {
+        return date('Y-m-d H:i:s', $unix_timestamp);
+    }
+    // }}}
+
+    // {{{ mdbstamp2Unix()
+
+    /**
+     * convert a MDB2 timestamp into a unix timestamp
+     *
+     * @param int a valid MDB2 timestamp
+     * @return string unix timestamp with the time stored in the MDB2 format
+     *
+     * @access public
+     */
+    function mdbstamp2Unix($mdb_timestamp)
+    {
+        $arr = MDB2_Date::mdbstamp2Date($mdb_timestamp);
+
+        return mktime($arr['hour'], $arr['minute'], $arr['second'], $arr['month'], $arr['day'], $arr['year'], -1);
+    }
+    // }}}
+
+    // {{{ mdbstamp2Date()
+
+    /**
+     * convert a MDB2 timestamp into an array containing all
+     * values necessary to pass to php's date() function
+     *
+     * @param int a valid MDB2 timestamp
+     *
+     * @return array with the time split
+     * @access public
+     */
+    function mdbstamp2Date($mdb_timestamp)
+    {
+        list($arr['year'], $arr['month'], $arr['day'], $arr['hour'], $arr['minute'], $arr['second']) =
+            sscanf($mdb_timestamp, "%04u-%02u-%02u %02u:%02u:%02u");
+        return $arr;
+    }
+    // }}}
+}
+
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Datatype/Common.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Datatype/Common.php
new file mode 100644 (file)
index 0000000..e1b738b
--- /dev/null
@@ -0,0 +1,1837 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: Common.php,v 1.126 2007/03/28 16:49:43 quipo Exp $
+
+require_once 'MDB2/LOB.php';
+
+/**
+ * @package  MDB2
+ * @category Database
+ * @author   Lukas Smith <smith@pooteeweet.org>
+ */
+
+/**
+ * MDB2_Driver_Common: Base class that is extended by each MDB2 driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_Datatype_Common extends MDB2_Module_Common
+{
+    var $valid_default_values = array(
+        'text'      => '',
+        'boolean'   => true,
+        'integer'   => 0,
+        'decimal'   => 0.0,
+        'float'     => 0.0,
+        'timestamp' => '1970-01-01 00:00:00',
+        'time'      => '00:00:00',
+        'date'      => '1970-01-01',
+        'clob'      => '',
+        'blob'      => '',
+    );
+
+    /**
+     * contains all LOB objects created with this MDB2 instance
+     * @var array
+     * @access protected
+     */
+    var $lobs = array();
+
+    // }}}
+    // {{{ getValidTypes()
+
+    /**
+     * Get the list of valid types
+     *
+     * This function returns an array of valid types as keys with the values
+     * being possible default values for all native datatypes and mapped types
+     * for custom datatypes.
+     *
+     * @return mixed array on success, a MDB2 error on failure
+     * @access public
+     */
+    function getValidTypes()
+    {
+        $types = $this->valid_default_values;
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+        if (!empty($db->options['datatype_map'])) {
+            foreach ($db->options['datatype_map'] as $type => $mapped_type) {
+                if (array_key_exists($mapped_type, $types)) {
+                    $types[$type] = $types[$mapped_type];
+                } elseif (!empty($db->options['datatype_map_callback'][$type])) {
+                    $parameter = array('type' => $type, 'mapped_type' => $mapped_type);
+                    $default =  call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
+                    $types[$type] = $default;
+                }
+            }
+        }
+        return $types;
+    }
+
+    // }}}
+    // {{{ checkResultTypes()
+
+    /**
+     * Define the list of types to be associated with the columns of a given
+     * result set.
+     *
+     * This function may be called before invoking fetchRow(), fetchOne()
+     * fetchCole() and fetchAll() so that the necessary data type
+     * conversions are performed on the data to be retrieved by them. If this
+     * function is not called, the type of all result set columns is assumed
+     * to be text, thus leading to not perform any conversions.
+     *
+     * @param array $types array variable that lists the
+     *       data types to be expected in the result set columns. If this array
+     *       contains less types than the number of columns that are returned
+     *       in the result set, the remaining columns are assumed to be of the
+     *       type text. Currently, the types clob and blob are not fully
+     *       supported.
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function checkResultTypes($types)
+    {
+        $types = is_array($types) ? $types : array($types);
+        foreach ($types as $key => $type) {
+            if (!isset($this->valid_default_values[$type])) {
+                $db =& $this->getDBInstance();
+                if (PEAR::isError($db)) {
+                    return $db;
+                }
+                if (empty($db->options['datatype_map'][$type])) {
+                    return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                        $type.' for '.$key.' is not a supported column type', __FUNCTION__);
+                }
+            }
+        }
+        return $types;
+    }
+
+    // }}}
+    // {{{ _baseConvertResult()
+
+    /**
+     * General type conversion method
+     *
+     * @param mixed   $value reference to a value to be converted
+     * @param string  $type  specifies which type to convert to
+     * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
+     * @return object an MDB2 error on failure
+     * @access protected
+     */
+    function _baseConvertResult($value, $type, $rtrim = true)
+    {
+        switch ($type) {
+        case 'text':
+            if ($rtrim) {
+                $value = rtrim($value);
+            }
+            return $value;
+        case 'integer':
+            return intval($value);
+        case 'boolean':
+            return !empty($value);
+        case 'decimal':
+            return $value;
+        case 'float':
+            return doubleval($value);
+        case 'date':
+            return $value;
+        case 'time':
+            return $value;
+        case 'timestamp':
+            return $value;
+        case 'clob':
+        case 'blob':
+            $this->lobs[] = array(
+                'buffer' => null,
+                'position' => 0,
+                'lob_index' => null,
+                'endOfLOB' => false,
+                'resource' => $value,
+                'value' => null,
+                'loaded' => false,
+            );
+            end($this->lobs);
+            $lob_index = key($this->lobs);
+            $this->lobs[$lob_index]['lob_index'] = $lob_index;
+            return fopen('MDB2LOB://'.$lob_index.'@'.$this->db_index, 'r+');
+        }
+
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_INVALID, null, null,
+            'attempt to convert result value to an unknown type :' . $type, __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ convertResult()
+
+    /**
+     * Convert a value to a RDBMS indipendent MDB2 type
+     *
+     * @param mixed   $value value to be converted
+     * @param string  $type  specifies which type to convert to
+     * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
+     * @return mixed converted value
+     * @access public
+     */
+    function convertResult($value, $type, $rtrim = true)
+    {
+        if (is_null($value)) {
+            return null;
+        }
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+        if (!empty($db->options['datatype_map'][$type])) {
+            $type = $db->options['datatype_map'][$type];
+            if (!empty($db->options['datatype_map_callback'][$type])) {
+                $parameter = array('type' => $type, 'value' => $value, 'rtrim' => $rtrim);
+                return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
+            }
+        }
+        return $this->_baseConvertResult($value, $type, $rtrim);
+    }
+
+    // }}}
+    // {{{ convertResultRow()
+
+    /**
+     * Convert a result row
+     *
+     * @param array   $types
+     * @param array   $row   specifies the types to convert to
+     * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
+     * @return mixed MDB2_OK on success, an MDB2 error on failure
+     * @access public
+     */
+    function convertResultRow($types, $row, $rtrim = true)
+    {
+        $types = $this->_sortResultFieldTypes(array_keys($row), $types);
+        foreach ($row as $key => $value) {
+            if (empty($types[$key])) {
+                continue;
+            }
+            $value = $this->convertResult($row[$key], $types[$key], $rtrim);
+            if (PEAR::isError($value)) {
+                return $value;
+            }
+            $row[$key] = $value;
+        }
+        return $row;
+    }
+
+    // }}}
+    // {{{ _sortResultFieldTypes()
+
+    /**
+     * convert a result row
+     *
+     * @param array $types
+     * @param array $row specifies the types to convert to
+     * @param bool   $rtrim   if to rtrim text values or not
+     * @return mixed MDB2_OK on success,  a MDB2 error on failure
+     * @access public
+     */
+    function _sortResultFieldTypes($columns, $types)
+    {
+        $n_cols = count($columns);
+        $n_types = count($types);
+        if ($n_cols > $n_types) {
+            for ($i= $n_cols - $n_types; $i >= 0; $i--) {
+                $types[] = null;
+            }
+        }
+        $sorted_types = array();
+        foreach ($columns as $col) {
+            $sorted_types[$col] = null;
+        }
+        foreach ($types as $name => $type) {
+            if (array_key_exists($name, $sorted_types)) {
+                $sorted_types[$name] = $type;
+                unset($types[$name]);
+            }
+        }
+        // if there are left types in the array, fill the null values of the
+        // sorted array with them, in order.
+        if (count($types)) {
+            reset($types);
+            foreach (array_keys($sorted_types) as $k) {
+                if (is_null($sorted_types[$k])) {
+                    $sorted_types[$k] = current($types);
+                    next($types);
+                }
+            }
+        }
+        return $sorted_types;
+    }
+
+    // }}}
+    // {{{ getDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare
+     * of the given type
+     *
+     * @param string $type type to which the value should be converted to
+     * @param string  $name   name the field to be declared.
+     * @param string  $field  definition of the field
+     * @return string  DBMS specific SQL code portion that should be used to
+     *                 declare the specified field.
+     * @access public
+     */
+    function getDeclaration($type, $name, $field)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        if (!empty($db->options['datatype_map'][$type])) {
+            $type = $db->options['datatype_map'][$type];
+            if (!empty($db->options['datatype_map_callback'][$type])) {
+                $parameter = array('type' => $type, 'name' => $name, 'field' => $field);
+                return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
+            }
+            $field['type'] = $type;
+        }
+
+        if (!method_exists($this, "_get{$type}Declaration")) {
+            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'type not defined: '.$type, __FUNCTION__);
+        }
+        return $this->{"_get{$type}Declaration"}($name, $field);
+    }
+
+    // }}}
+    // {{{ getTypeDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare an text type
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param array $field  associative array with the name of the properties
+     *      of the field being declared as array indexes. Currently, the types
+     *      of supported field properties are as follows:
+     *
+     *      length
+     *          Integer value that determines the maximum length of the text
+     *          field. If this argument is missing the field should be
+     *          declared to have the longest length allowed by the DBMS.
+     *
+     *      default
+     *          Text value to be used as default for this field.
+     *
+     *      notnull
+     *          Boolean flag that indicates whether this field is constrained
+     *          to not be set to null.
+     * @return string  DBMS specific SQL code portion that should be used to
+     *      declare the specified field.
+     * @access public
+     */
+    function getTypeDeclaration($field)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        switch ($field['type']) {
+        case 'text':
+            $length = !empty($field['length']) ? $field['length'] : $db->options['default_text_field_length'];
+            $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
+            return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
+                : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
+        case 'clob':
+            return 'TEXT';
+        case 'blob':
+            return 'TEXT';
+        case 'integer':
+            return 'INT';
+        case 'boolean':
+            return 'INT';
+        case 'date':
+            return 'CHAR ('.strlen('YYYY-MM-DD').')';
+        case 'time':
+            return 'CHAR ('.strlen('HH:MM:SS').')';
+        case 'timestamp':
+            return 'CHAR ('.strlen('YYYY-MM-DD HH:MM:SS').')';
+        case 'float':
+            return 'TEXT';
+        case 'decimal':
+            return 'TEXT';
+        }
+        return '';
+    }
+
+    // }}}
+    // {{{ _getDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare a generic type
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param string $name   name the field to be declared.
+     * @param array  $field  associative array with the name of the properties
+     *      of the field being declared as array indexes. Currently, the types
+     *      of supported field properties are as follows:
+     *
+     *      length
+     *          Integer value that determines the maximum length of the text
+     *          field. If this argument is missing the field should be
+     *          declared to have the longest length allowed by the DBMS.
+     *
+     *      default
+     *          Text value to be used as default for this field.
+     *
+     *      notnull
+     *          Boolean flag that indicates whether this field is constrained
+     *          to not be set to null.
+     *      charset
+     *          Text value with the default CHARACTER SET for this field.
+     *      collation
+     *          Text value with the default COLLATION for this field.
+     * @return string  DBMS specific SQL code portion that should be used to
+     *      declare the specified field, or a MDB2_Error on failure
+     * @access protected
+     */
+    function _getDeclaration($name, $field)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $name = $db->quoteIdentifier($name, true);
+        $declaration_options = $db->datatype->_getDeclarationOptions($field);
+        if (PEAR::isError($declaration_options)) {
+            return $declaration_options;
+        }
+        return $name.' '.$this->getTypeDeclaration($field).$declaration_options;
+    }
+
+    // }}}
+    // {{{ _getDeclarationOptions()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare a generic type
+     * field to be used in statement like CREATE TABLE, without the field name
+     * and type values (ie. just the character set, default value, if the
+     * field is permitted to be NULL or not, and the collation options).
+     *
+     * @param array  $field  associative array with the name of the properties
+     *      of the field being declared as array indexes. Currently, the types
+     *      of supported field properties are as follows:
+     *
+     *      default
+     *          Text value to be used as default for this field.
+     *      notnull
+     *          Boolean flag that indicates whether this field is constrained
+     *          to not be set to null.
+     *      charset
+     *          Text value with the default CHARACTER SET for this field.
+     *      collation
+     *          Text value with the default COLLATION for this field.
+     * @return string  DBMS specific SQL code portion that should be used to
+     *      declare the specified field's options.
+     * @access protected
+     */
+    function _getDeclarationOptions($field)
+    {
+        $charset = empty($field['charset']) ? '' :
+            ' '.$this->_getCharsetFieldDeclaration($field['charset']);
+
+        $default = '';
+        if (array_key_exists('default', $field)) {
+            if ($field['default'] === '') {
+                $db =& $this->getDBInstance();
+                if (PEAR::isError($db)) {
+                    return $db;
+                }
+                if (empty($field['notnull'])) {
+                    $field['default'] = null;
+                } else {
+                    $valid_default_values = $this->getValidTypes();
+                    $field['default'] = $valid_default_values[$field['type']];
+                }
+                if ($field['default'] === ''
+                    && ($db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)
+                ) {
+                    $field['default'] = ' ';
+                }
+            }
+            $default = ' DEFAULT '.$this->quote($field['default'], $field['type']);
+        } elseif (empty($field['notnull'])) {
+            $default = ' DEFAULT NULL';
+        }
+
+        $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
+        
+        $collation = empty($field['collation']) ? '' :
+            ' '.$this->_getCollationFieldDeclaration($field['collation']);
+        return $charset.$default.$notnull.$collation;
+    }
+
+    // }}}
+    // {{{ _getCharsetFieldDeclaration()
+    
+    /**
+     * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
+     * of a field declaration to be used in statements like CREATE TABLE.
+     *
+     * @param string $charset   name of the charset
+     * @return string  DBMS specific SQL code portion needed to set the CHARACTER SET
+     *                 of a field declaration.
+     */
+    function _getCharsetFieldDeclaration($charset)
+    {
+        return '';
+    }
+
+    // }}}
+    // {{{ _getCollationFieldDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to set the COLLATION
+     * of a field declaration to be used in statements like CREATE TABLE.
+     *
+     * @param string $collation   name of the collation
+     * @return string  DBMS specific SQL code portion needed to set the COLLATION
+     *                 of a field declaration.
+     */
+    function _getCollationFieldDeclaration($collation)
+    {
+        return '';
+    }
+
+    // }}}
+    // {{{ _getIntegerDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare an integer type
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param string $name name the field to be declared.
+     * @param array $field associative array with the name of the properties
+     *       of the field being declared as array indexes. Currently, the types
+     *       of supported field properties are as follows:
+     *
+     *       unsigned
+     *           Boolean flag that indicates whether the field should be
+     *           declared as unsigned integer if possible.
+     *
+     *       default
+     *           Integer value to be used as default for this field.
+     *
+     *       notnull
+     *           Boolean flag that indicates whether this field is constrained
+     *           to not be set to null.
+     * @return string DBMS specific SQL code portion that should be used to
+     *       declare the specified field.
+     * @access protected
+     */
+    function _getIntegerDeclaration($name, $field)
+    {
+        if (!empty($field['unsigned'])) {
+            $db =& $this->getDBInstance();
+            if (PEAR::isError($db)) {
+                return $db;
+            }
+
+            $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
+        }
+        return $this->_getDeclaration($name, $field);
+    }
+
+    // }}}
+    // {{{ _getTextDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare an text type
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param string $name name the field to be declared.
+     * @param array $field associative array with the name of the properties
+     *       of the field being declared as array indexes. Currently, the types
+     *       of supported field properties are as follows:
+     *
+     *       length
+     *           Integer value that determines the maximum length of the text
+     *           field. If this argument is missing the field should be
+     *           declared to have the longest length allowed by the DBMS.
+     *
+     *       default
+     *           Text value to be used as default for this field.
+     *
+     *       notnull
+     *           Boolean flag that indicates whether this field is constrained
+     *           to not be set to null.
+     * @return string DBMS specific SQL code portion that should be used to
+     *       declare the specified field.
+     * @access protected
+     */
+    function _getTextDeclaration($name, $field)
+    {
+        return $this->_getDeclaration($name, $field);
+    }
+
+    // }}}
+    // {{{ _getCLOBDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare an character
+     * large object type field to be used in statements like CREATE TABLE.
+     *
+     * @param string $name name the field to be declared.
+     * @param array $field associative array with the name of the properties
+     *        of the field being declared as array indexes. Currently, the types
+     *        of supported field properties are as follows:
+     *
+     *        length
+     *            Integer value that determines the maximum length of the large
+     *            object field. If this argument is missing the field should be
+     *            declared to have the longest length allowed by the DBMS.
+     *
+     *        notnull
+     *            Boolean flag that indicates whether this field is constrained
+     *            to not be set to null.
+     * @return string DBMS specific SQL code portion that should be used to
+     *        declare the specified field.
+     * @access public
+     */
+    function _getCLOBDeclaration($name, $field)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
+        $name = $db->quoteIdentifier($name, true);
+        return $name.' '.$this->getTypeDeclaration($field).$notnull;
+    }
+
+    // }}}
+    // {{{ _getBLOBDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare an binary large
+     * object type field to be used in statements like CREATE TABLE.
+     *
+     * @param string $name name the field to be declared.
+     * @param array $field associative array with the name of the properties
+     *        of the field being declared as array indexes. Currently, the types
+     *        of supported field properties are as follows:
+     *
+     *        length
+     *            Integer value that determines the maximum length of the large
+     *            object field. If this argument is missing the field should be
+     *            declared to have the longest length allowed by the DBMS.
+     *
+     *        notnull
+     *            Boolean flag that indicates whether this field is constrained
+     *            to not be set to null.
+     * @return string DBMS specific SQL code portion that should be used to
+     *        declare the specified field.
+     * @access protected
+     */
+    function _getBLOBDeclaration($name, $field)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
+        $name = $db->quoteIdentifier($name, true);
+        return $name.' '.$this->getTypeDeclaration($field).$notnull;
+    }
+
+    // }}}
+    // {{{ _getBooleanDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare a boolean type
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param string $name name the field to be declared.
+     * @param array $field associative array with the name of the properties
+     *       of the field being declared as array indexes. Currently, the types
+     *       of supported field properties are as follows:
+     *
+     *       default
+     *           Boolean value to be used as default for this field.
+     *
+     *       notnullL
+     *           Boolean flag that indicates whether this field is constrained
+     *           to not be set to null.
+     * @return string DBMS specific SQL code portion that should be used to
+     *       declare the specified field.
+     * @access protected
+     */
+    function _getBooleanDeclaration($name, $field)
+    {
+        return $this->_getDeclaration($name, $field);
+    }
+
+    // }}}
+    // {{{ _getDateDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare a date type
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param string $name name the field to be declared.
+     * @param array $field associative array with the name of the properties
+     *       of the field being declared as array indexes. Currently, the types
+     *       of supported field properties are as follows:
+     *
+     *       default
+     *           Date value to be used as default for this field.
+     *
+     *       notnull
+     *           Boolean flag that indicates whether this field is constrained
+     *           to not be set to null.
+     * @return string DBMS specific SQL code portion that should be used to
+     *       declare the specified field.
+     * @access protected
+     */
+    function _getDateDeclaration($name, $field)
+    {
+        return $this->_getDeclaration($name, $field);
+    }
+
+    // }}}
+    // {{{ _getTimestampDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare a timestamp
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param string $name name the field to be declared.
+     * @param array $field associative array with the name of the properties
+     *       of the field being declared as array indexes. Currently, the types
+     *       of supported field properties are as follows:
+     *
+     *       default
+     *           Timestamp value to be used as default for this field.
+     *
+     *       notnull
+     *           Boolean flag that indicates whether this field is constrained
+     *           to not be set to null.
+     * @return string DBMS specific SQL code portion that should be used to
+     *       declare the specified field.
+     * @access protected
+     */
+    function _getTimestampDeclaration($name, $field)
+    {
+        return $this->_getDeclaration($name, $field);
+    }
+
+    // }}}
+    // {{{ _getTimeDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare a time
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param string $name name the field to be declared.
+     * @param array $field associative array with the name of the properties
+     *       of the field being declared as array indexes. Currently, the types
+     *       of supported field properties are as follows:
+     *
+     *       default
+     *           Time value to be used as default for this field.
+     *
+     *       notnull
+     *           Boolean flag that indicates whether this field is constrained
+     *           to not be set to null.
+     * @return string DBMS specific SQL code portion that should be used to
+     *       declare the specified field.
+     * @access protected
+     */
+    function _getTimeDeclaration($name, $field)
+    {
+        return $this->_getDeclaration($name, $field);
+    }
+
+    // }}}
+    // {{{ _getFloatDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare a float type
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param string $name name the field to be declared.
+     * @param array $field associative array with the name of the properties
+     *       of the field being declared as array indexes. Currently, the types
+     *       of supported field properties are as follows:
+     *
+     *       default
+     *           Float value to be used as default for this field.
+     *
+     *       notnull
+     *           Boolean flag that indicates whether this field is constrained
+     *           to not be set to null.
+     * @return string DBMS specific SQL code portion that should be used to
+     *       declare the specified field.
+     * @access protected
+     */
+    function _getFloatDeclaration($name, $field)
+    {
+        return $this->_getDeclaration($name, $field);
+    }
+
+    // }}}
+    // {{{ _getDecimalDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare a decimal type
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param string $name name the field to be declared.
+     * @param array $field associative array with the name of the properties
+     *       of the field being declared as array indexes. Currently, the types
+     *       of supported field properties are as follows:
+     *
+     *       default
+     *           Decimal value to be used as default for this field.
+     *
+     *       notnull
+     *           Boolean flag that indicates whether this field is constrained
+     *           to not be set to null.
+     * @return string DBMS specific SQL code portion that should be used to
+     *       declare the specified field.
+     * @access protected
+     */
+    function _getDecimalDeclaration($name, $field)
+    {
+        return $this->_getDeclaration($name, $field);
+    }
+
+    // }}}
+    // {{{ compareDefinition()
+
+    /**
+     * Obtain an array of changes that may need to applied
+     *
+     * @param array $current new definition
+     * @param array  $previous old definition
+     * @return array  containing all changes that will need to be applied
+     * @access public
+     */
+    function compareDefinition($current, $previous)
+    {
+        $type = !empty($current['type']) ? $current['type'] : null;
+
+        if (!method_exists($this, "_compare{$type}Definition")) {
+            $db =& $this->getDBInstance();
+            if (PEAR::isError($db)) {
+                return $db;
+            }
+            if (!empty($db->options['datatype_map_callback'][$type])) {
+                $parameter = array('current' => $current, 'previous' => $previous);
+                $change =  call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
+                return $change;
+            }
+            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'type "'.$current['type'].'" is not yet supported', __FUNCTION__);
+        }
+
+        if (empty($previous['type']) || $previous['type'] != $type) {
+            return $current;
+        }
+
+        $change = $this->{"_compare{$type}Definition"}($current, $previous);
+
+        if ($previous['type'] != $type) {
+            $change['type'] = true;
+        }
+
+        $previous_notnull = !empty($previous['notnull']) ? $previous['notnull'] : false;
+        $notnull = !empty($current['notnull']) ? $current['notnull'] : false;
+        if ($previous_notnull != $notnull) {
+            $change['notnull'] = true;
+        }
+
+        $previous_default = array_key_exists('default', $previous) ? $previous['default'] :
+            ($previous_notnull ? '' : null);
+        $default = array_key_exists('default', $current) ? $current['default'] :
+            ($notnull ? '' : null);
+        if ($previous_default !== $default) {
+            $change['default'] = true;
+        }
+
+        return $change;
+    }
+
+    // }}}
+    // {{{ _compareIntegerDefinition()
+
+    /**
+     * Obtain an array of changes that may need to applied to an integer field
+     *
+     * @param array $current new definition
+     * @param array  $previous old definition
+     * @return array  containing all changes that will need to be applied
+     * @access protected
+     */
+    function _compareIntegerDefinition($current, $previous)
+    {
+        $change = array();
+        $previous_unsigned = !empty($previous['unsigned']) ? $previous['unsigned'] : false;
+        $unsigned = !empty($current['unsigned']) ? $current['unsigned'] : false;
+        if ($previous_unsigned != $unsigned) {
+            $change['unsigned'] = true;
+        }
+        $previous_autoincrement = !empty($previous['autoincrement']) ? $previous['autoincrement'] : false;
+        $autoincrement = !empty($current['autoincrement']) ? $current['autoincrement'] : false;
+        if ($previous_autoincrement != $autoincrement) {
+            $change['autoincrement'] = true;
+        }
+        return $change;
+    }
+
+    // }}}
+    // {{{ _compareTextDefinition()
+
+    /**
+     * Obtain an array of changes that may need to applied to an text field
+     *
+     * @param array $current new definition
+     * @param array  $previous old definition
+     * @return array  containing all changes that will need to be applied
+     * @access protected
+     */
+    function _compareTextDefinition($current, $previous)
+    {
+        $change = array();
+        $previous_length = !empty($previous['length']) ? $previous['length'] : 0;
+        $length = !empty($current['length']) ? $current['length'] : 0;
+        if ($previous_length != $length) {
+            $change['length'] = true;
+        }
+        $previous_fixed = !empty($previous['fixed']) ? $previous['fixed'] : 0;
+        $fixed = !empty($current['fixed']) ? $current['fixed'] : 0;
+        if ($previous_fixed != $fixed) {
+            $change['fixed'] = true;
+        }
+        return $change;
+    }
+
+    // }}}
+    // {{{ _compareCLOBDefinition()
+
+    /**
+     * Obtain an array of changes that may need to applied to an CLOB field
+     *
+     * @param array $current new definition
+     * @param array  $previous old definition
+     * @return array  containing all changes that will need to be applied
+     * @access protected
+     */
+    function _compareCLOBDefinition($current, $previous)
+    {
+        return $this->_compareTextDefinition($current, $previous);
+    }
+
+    // }}}
+    // {{{ _compareBLOBDefinition()
+
+    /**
+     * Obtain an array of changes that may need to applied to an BLOB field
+     *
+     * @param array $current new definition
+     * @param array  $previous old definition
+     * @return array  containing all changes that will need to be applied
+     * @access protected
+     */
+    function _compareBLOBDefinition($current, $previous)
+    {
+        return $this->_compareTextDefinition($current, $previous);
+    }
+
+    // }}}
+    // {{{ _compareDateDefinition()
+
+    /**
+     * Obtain an array of changes that may need to applied to an date field
+     *
+     * @param array $current new definition
+     * @param array  $previous old definition
+     * @return array  containing all changes that will need to be applied
+     * @access protected
+     */
+    function _compareDateDefinition($current, $previous)
+    {
+        return array();
+    }
+
+    // }}}
+    // {{{ _compareTimeDefinition()
+
+    /**
+     * Obtain an array of changes that may need to applied to an time field
+     *
+     * @param array $current new definition
+     * @param array  $previous old definition
+     * @return array  containing all changes that will need to be applied
+     * @access protected
+     */
+    function _compareTimeDefinition($current, $previous)
+    {
+        return array();
+    }
+
+    // }}}
+    // {{{ _compareTimestampDefinition()
+
+    /**
+     * Obtain an array of changes that may need to applied to an timestamp field
+     *
+     * @param array $current new definition
+     * @param array  $previous old definition
+     * @return array  containing all changes that will need to be applied
+     * @access protected
+     */
+    function _compareTimestampDefinition($current, $previous)
+    {
+        return array();
+    }
+
+    // }}}
+    // {{{ _compareBooleanDefinition()
+
+    /**
+     * Obtain an array of changes that may need to applied to an boolean field
+     *
+     * @param array $current new definition
+     * @param array  $previous old definition
+     * @return array  containing all changes that will need to be applied
+     * @access protected
+     */
+    function _compareBooleanDefinition($current, $previous)
+    {
+        return array();
+    }
+
+    // }}}
+    // {{{ _compareFloatDefinition()
+
+    /**
+     * Obtain an array of changes that may need to applied to an float field
+     *
+     * @param array $current new definition
+     * @param array  $previous old definition
+     * @return array  containing all changes that will need to be applied
+     * @access protected
+     */
+    function _compareFloatDefinition($current, $previous)
+    {
+        return array();
+    }
+
+    // }}}
+    // {{{ _compareDecimalDefinition()
+
+    /**
+     * Obtain an array of changes that may need to applied to an decimal field
+     *
+     * @param array $current new definition
+     * @param array  $previous old definition
+     * @return array  containing all changes that will need to be applied
+     * @access protected
+     */
+    function _compareDecimalDefinition($current, $previous)
+    {
+        return array();
+    }
+
+    // }}}
+    // {{{ quote()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @param string $type type to which the value should be converted to
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
+     * @return string text string that represents the given argument value in
+     *       a DBMS specific format.
+     * @access public
+     */
+    function quote($value, $type = null, $quote = true, $escape_wildcards = false)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        if (is_null($value)
+            || ($value === '' && $db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)
+        ) {
+            if (!$quote) {
+                return null;
+            }
+            return 'NULL';
+        }
+
+        if (is_null($type)) {
+            switch (gettype($value)) {
+            case 'integer':
+                $type = 'integer';
+                break;
+            case 'double':
+                // todo: default to decimal as float is quite unusual
+                // $type = 'float';
+                $type = 'decimal';
+                break;
+            case 'boolean':
+                $type = 'boolean';
+                break;
+            case 'array':
+                 $value = serialize($value);
+            case 'object':
+                 $type = 'text';
+                break;
+            default:
+                if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $value)) {
+                    $type = 'timestamp';
+                } elseif (preg_match('/^\d{2}:\d{2}$/', $value)) {
+                    $type = 'time';
+                } elseif (preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) {
+                    $type = 'date';
+                } else {
+                    $type = 'text';
+                }
+                break;
+            }
+        } elseif (!empty($db->options['datatype_map'][$type])) {
+            $type = $db->options['datatype_map'][$type];
+            if (!empty($db->options['datatype_map_callback'][$type])) {
+                $parameter = array('type' => $type, 'value' => $value, 'quote' => $quote, 'escape_wildcards' => $escape_wildcards);
+                return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
+            }
+        }
+
+        if (!method_exists($this, "_quote{$type}")) {
+            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'type not defined: '.$type, __FUNCTION__);
+        }
+        $value = $this->{"_quote{$type}"}($value, $quote, $escape_wildcards);
+        if ($quote && $escape_wildcards && $db->string_quoting['escape_pattern']
+            && $db->string_quoting['escape'] !== $db->string_quoting['escape_pattern']
+        ) {
+            $value.= $this->patternEscapeString();
+        }
+        return $value;
+    }
+
+    // }}}
+    // {{{ _quoteInteger()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
+     * @return string text string that represents the given argument value in
+     *       a DBMS specific format.
+     * @access protected
+     */
+    function _quoteInteger($value, $quote, $escape_wildcards)
+    {
+        return (int)$value;
+    }
+
+    // }}}
+    // {{{ _quoteText()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
+     * @return string text string that already contains any DBMS specific
+     *       escaped character sequences.
+     * @access protected
+     */
+    function _quoteText($value, $quote, $escape_wildcards)
+    {
+        if (!$quote) {
+            return $value;
+        }
+
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $value = $db->escape($value, $escape_wildcards);
+        if (PEAR::isError($value)) {
+            return $value;
+        }
+        return "'".$value."'";
+    }
+
+    // }}}
+    // {{{ _readFile()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @return string text string that represents the given argument value in
+     *       a DBMS specific format.
+     * @access protected
+     */
+    function _readFile($value)
+    {
+        $close = false;
+        if (preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) {
+            $close = true;
+            if ($match[1] == 'file://') {
+                $value = $match[2];
+            }
+            $value = @fopen($value, 'r');
+        }
+
+        if (is_resource($value)) {
+            $db =& $this->getDBInstance();
+            if (PEAR::isError($db)) {
+                return $db;
+            }
+
+            $fp = $value;
+            $value = '';
+            while (!@feof($fp)) {
+                $value.= @fread($fp, $db->options['lob_buffer_length']);
+            }
+            if ($close) {
+                @fclose($fp);
+            }
+        }
+
+        return $value;
+    }
+
+    // }}}
+    // {{{ _quoteLOB()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
+     * @return string text string that represents the given argument value in
+     *       a DBMS specific format.
+     * @access protected
+     */
+    function _quoteLOB($value, $quote, $escape_wildcards)
+    {
+        $value = $this->_readFile($value);
+        if (PEAR::isError($value)) {
+            return $value;
+        }
+        return $this->_quoteText($value, $quote, $escape_wildcards);
+    }
+
+    // }}}
+    // {{{ _quoteCLOB()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
+     * @return string text string that represents the given argument value in
+     *       a DBMS specific format.
+     * @access protected
+     */
+    function _quoteCLOB($value, $quote, $escape_wildcards)
+    {
+        return $this->_quoteLOB($value, $quote, $escape_wildcards);
+    }
+
+    // }}}
+    // {{{ _quoteBLOB()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
+     * @return string text string that represents the given argument value in
+     *       a DBMS specific format.
+     * @access protected
+     */
+    function _quoteBLOB($value, $quote, $escape_wildcards)
+    {
+        return $this->_quoteLOB($value, $quote, $escape_wildcards);
+    }
+
+    // }}}
+    // {{{ _quoteBoolean()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
+     * @return string text string that represents the given argument value in
+     *       a DBMS specific format.
+     * @access protected
+     */
+    function _quoteBoolean($value, $quote, $escape_wildcards)
+    {
+        return ($value ? 1 : 0);
+    }
+
+    // }}}
+    // {{{ _quoteDate()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
+     * @return string text string that represents the given argument value in
+     *       a DBMS specific format.
+     * @access protected
+     */
+    function _quoteDate($value, $quote, $escape_wildcards)
+    {
+        if ($value === 'CURRENT_DATE') {
+            $db =& $this->getDBInstance();
+            if (PEAR::isError($db)) {
+                return $db;
+            }
+            if (isset($db->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) {
+                return $db->function->now('date');
+            }
+            return 'CURRENT_DATE';
+        }
+        return $this->_quoteText($value, $quote, $escape_wildcards);
+    }
+
+    // }}}
+    // {{{ _quoteTimestamp()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
+     * @return string text string that represents the given argument value in
+     *       a DBMS specific format.
+     * @access protected
+     */
+    function _quoteTimestamp($value, $quote, $escape_wildcards)
+    {
+        if ($value === 'CURRENT_TIMESTAMP') {
+            $db =& $this->getDBInstance();
+            if (PEAR::isError($db)) {
+                return $db;
+            }
+            if (isset($db->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) {
+                return $db->function->now('timestamp');
+            }
+            return 'CURRENT_TIMESTAMP';
+        }
+        return $this->_quoteText($value, $quote, $escape_wildcards);
+    }
+
+    // }}}
+    // {{{ _quoteTime()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     *       compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
+     * @return string text string that represents the given argument value in
+     *       a DBMS specific format.
+     * @access protected
+     */
+    function _quoteTime($value, $quote, $escape_wildcards)
+    {
+        if ($value === 'CURRENT_TIME') {
+            $db =& $this->getDBInstance();
+            if (PEAR::isError($db)) {
+                return $db;
+            }
+            if (isset($db->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) {
+                return $db->function->now('time');
+            }
+            return 'CURRENT_TIME';
+        }
+        return $this->_quoteText($value, $quote, $escape_wildcards);
+    }
+
+    // }}}
+    // {{{ _quoteFloat()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
+     * @return string text string that represents the given argument value in
+     *       a DBMS specific format.
+     * @access protected
+     */
+    function _quoteFloat($value, $quote, $escape_wildcards)
+    {
+        if (preg_match('/^(.*)e([-+])(\d+)$/i', $value, $matches)) {
+            $decimal = $this->_quoteDecimal($matches[1], $quote, $escape_wildcards);
+            $sign = $matches[2];
+            $exponent = str_pad($matches[3], 2, '0', STR_PAD_LEFT);
+            $value = $decimal.'E'.$sign.$exponent;
+        } else {
+            $value = $this->_quoteDecimal($value, $quote, $escape_wildcards);
+        }
+        return $value;
+    }
+
+    // }}}
+    // {{{ _quoteDecimal()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
+     * @return string text string that represents the given argument value in
+     *       a DBMS specific format.
+     * @access protected
+     */
+    function _quoteDecimal($value, $quote, $escape_wildcards)
+    {
+        $value = (string)$value;
+        $value = preg_replace('/[^\d\.,\-+eE]/', '', $value);
+        if (preg_match('/[^.0-9]/', $value)) {
+            if (strpos($value, ',')) {
+                // 1000,00
+                if (!strpos($value, '.')) {
+                    // convert the last "," to a "."
+                    $value = strrev(str_replace(',', '.', strrev($value)));
+                // 1.000,00
+                } elseif (strpos($value, '.') && strpos($value, '.') < strpos($value, ',')) {
+                    $value = str_replace('.', '', $value);
+                    // convert the last "," to a "."
+                    $value = strrev(str_replace(',', '.', strrev($value)));
+                // 1,000.00
+                } else {
+                    $value = str_replace(',', '', $value);
+                }
+            }
+        }
+        return $value;
+    }
+
+    // }}}
+    // {{{ writeLOBToFile()
+
+    /**
+     * retrieve LOB from the database
+     *
+     * @param resource $lob stream handle
+     * @param string $file name of the file into which the LOb should be fetched
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access protected
+     */
+    function writeLOBToFile($lob, $file)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        if (preg_match('/^(\w+:\/\/)(.*)$/', $file, $match)) {
+            if ($match[1] == 'file://') {
+                $file = $match[2];
+            }
+        }
+
+        $fp = @fopen($file, 'wb');
+        while (!@feof($lob)) {
+            $result = @fread($lob, $db->options['lob_buffer_length']);
+            $read = strlen($result);
+            if (@fwrite($fp, $result, $read) != $read) {
+                @fclose($fp);
+                return $db->raiseError(MDB2_ERROR, null, null,
+                    'could not write to the output file', __FUNCTION__);
+            }
+        }
+        @fclose($fp);
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ _retrieveLOB()
+
+    /**
+     * retrieve LOB from the database
+     *
+     * @param array $lob array
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access protected
+     */
+    function _retrieveLOB(&$lob)
+    {
+        if (is_null($lob['value'])) {
+            $lob['value'] = $lob['resource'];
+        }
+        $lob['loaded'] = true;
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ readLOB()
+
+    /**
+     * Read data from large object input stream.
+     *
+     * @param resource $lob stream handle
+     * @param string $data reference to a variable that will hold data
+     *                          to be read from the large object input stream
+     * @param integer $length    value that indicates the largest ammount ofdata
+     *                          to be read from the large object input stream.
+     * @return mixed the effective number of bytes read from the large object
+     *                      input stream on sucess or an MDB2 error object.
+     * @access public
+     * @see endOfLOB()
+     */
+    function _readLOB($lob, $length)
+    {
+        return substr($lob['value'], $lob['position'], $length);
+    }
+
+    // }}}
+    // {{{ _endOfLOB()
+
+    /**
+     * Determine whether it was reached the end of the large object and
+     * therefore there is no more data to be read for the its input stream.
+     *
+     * @param array $lob array
+     * @return mixed true or false on success, a MDB2 error on failure
+     * @access protected
+     */
+    function _endOfLOB($lob)
+    {
+        return $lob['endOfLOB'];
+    }
+
+    // }}}
+    // {{{ destroyLOB()
+
+    /**
+     * Free any resources allocated during the lifetime of the large object
+     * handler object.
+     *
+     * @param resource $lob stream handle
+     * @access public
+     */
+    function destroyLOB($lob)
+    {
+        $lob_data = stream_get_meta_data($lob);
+        $lob_index = $lob_data['wrapper_data']->lob_index;
+        fclose($lob);
+        if (isset($this->lobs[$lob_index])) {
+            $this->_destroyLOB($this->lobs[$lob_index]);
+            unset($this->lobs[$lob_index]);
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ _destroyLOB()
+
+    /**
+     * Free any resources allocated during the lifetime of the large object
+     * handler object.
+     *
+     * @param array $lob array
+     * @access private
+     */
+    function _destroyLOB(&$lob)
+    {
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ implodeArray()
+
+    /**
+     * apply a type to all values of an array and return as a comma seperated string
+     * useful for generating IN statements
+     *
+     * @access public
+     *
+     * @param array $array data array
+     * @param string $type determines type of the field
+     *
+     * @return string comma seperated values
+     */
+    function implodeArray($array, $type = false)
+    {
+        if (!is_array($array) || empty($array)) {
+            return 'NULL';
+        }
+        if ($type) {
+            foreach ($array as $value) {
+                $return[] = $this->quote($value, $type);
+            }
+        } else {
+            $return = $array;
+        }
+        return implode(', ', $return);
+    }
+
+    // }}}
+    // {{{ matchPattern()
+
+    /**
+     * build a pattern matching string
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change signature at
+     * any time until labelled as non-experimental
+     *
+     * @access public
+     *
+     * @param array $pattern even keys are strings, odd are patterns (% and _)
+     * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
+     * @param string $field optional field name that is being matched against
+     *                  (might be required when emulating ILIKE)
+     *
+     * @return string SQL pattern
+     */
+    function matchPattern($pattern, $operator = null, $field = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $match = '';
+        if (!is_null($operator)) {
+            $operator = strtoupper($operator);
+            switch ($operator) {
+            // case insensitive
+            case 'ILIKE':
+                if (is_null($field)) {
+                    return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                        'case insensitive LIKE matching requires passing the field name', __FUNCTION__);
+                }
+                $db->loadModule('Function', null, true);
+                $match = $db->function->lower($field).' LIKE ';
+                break;
+            // case sensitive
+            case 'LIKE':
+                $match = is_null($field) ? 'LIKE ' : $field.' LIKE ';
+                break;
+            default:
+                return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                    'not a supported operator type:'. $operator, __FUNCTION__);
+            }
+        }
+        $match.= "'";
+        foreach ($pattern as $key => $value) {
+            if ($key % 2) {
+                $match.= $value;
+            } else {
+                if ($operator === 'ILIKE') {
+                    $value = strtolower($value);
+                }
+                $escaped = $db->escape($value);
+                if (PEAR::isError($escaped)) {
+                    return $escaped;
+                }
+                $match.= $db->escapePattern($escaped);
+            }
+        }
+        $match.= "'";
+        $match.= $this->patternEscapeString();
+        return $match;
+    }
+
+    // }}}
+    // {{{ patternEscapeString()
+
+    /**
+     * build string to define pattern escape character
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change signature at
+     * any time until labelled as non-experimental
+     *
+     * @access public
+     *
+     * @return string define pattern escape character
+     */
+    function patternEscapeString()
+    {
+        return '';
+    }
+
+    // }}}
+    // {{{ mapNativeDatatype()
+
+    /**
+     * Maps a native array description of a field to a MDB2 datatype and length
+     *
+     * @param array  $field native field description
+     * @return array containing the various possible types, length, sign, fixed
+     * @access public
+     */
+    function mapNativeDatatype($field)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        // If the user has specified an option to map the native field
+        // type to a custom MDB2 datatype...
+        $db_type = strtok($field['type'], '(), ');
+        if (!empty($db->options['nativetype_map_callback'][$db_type])) {
+            return call_user_func_array($db->options['nativetype_map_callback'][$db_type], array($db, $field));
+        }
+
+        // Otherwise perform the built-in (i.e. normal) MDB2 native type to
+        // MDB2 datatype conversion
+        return $this->_mapNativeDatatype($field);
+    }
+
+    // }}}
+    // {{{ _mapNativeDatatype()
+
+    /**
+     * Maps a native array description of a field to a MDB2 datatype and length
+     *
+     * @param array  $field native field description
+     * @return array containing the various possible types, length, sign, fixed
+     * @access public
+     */
+    function _mapNativeDatatype($field)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ mapPrepareDatatype()
+
+    /**
+     * Maps an mdb2 datatype to mysqli prepare type
+     *
+     * @param string $type
+     * @return string
+     * @access public
+     */
+    function mapPrepareDatatype($type)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        if (!empty($db->options['datatype_map'][$type])) {
+            $type = $db->options['datatype_map'][$type];
+            if (!empty($db->options['datatype_map_callback'][$type])) {
+                $parameter = array('type' => $type);
+                return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
+            }
+        }
+
+        return $type;
+    }
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Datatype/mysql.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Datatype/mysql.php
new file mode 100644 (file)
index 0000000..34db8f3
--- /dev/null
@@ -0,0 +1,471 @@
+<?php
+// vim: set et ts=4 sw=4 fdm=marker:
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: mysql.php,v 1.60 2007/03/28 16:58:54 quipo Exp $
+//
+
+require_once 'MDB2/Driver/Datatype/Common.php';
+
+/**
+ * MDB2 MySQL driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_Datatype_mysql extends MDB2_Driver_Datatype_Common
+{
+    // {{{ _getCharsetFieldDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
+     * of a field declaration to be used in statements like CREATE TABLE.
+     *
+     * @param string $charset   name of the charset
+     * @return string  DBMS specific SQL code portion needed to set the CHARACTER SET
+     *                 of a field declaration.
+     */
+    function _getCharsetFieldDeclaration($charset)
+    {
+        return 'CHARACTER SET '.$charset;
+    }
+
+    // }}}
+    // {{{ _getCollationFieldDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to set the COLLATION
+     * of a field declaration to be used in statements like CREATE TABLE.
+     *
+     * @param string $collation   name of the collation
+     * @return string  DBMS specific SQL code portion needed to set the COLLATION
+     *                 of a field declaration.
+     */
+    function _getCollationFieldDeclaration($collation)
+    {
+        return 'COLLATE '.$collation;
+    }
+
+    // }}}
+    // {{{ getTypeDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare an text type
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param array $field  associative array with the name of the properties
+     *      of the field being declared as array indexes. Currently, the types
+     *      of supported field properties are as follows:
+     *
+     *      length
+     *          Integer value that determines the maximum length of the text
+     *          field. If this argument is missing the field should be
+     *          declared to have the longest length allowed by the DBMS.
+     *
+     *      default
+     *          Text value to be used as default for this field.
+     *
+     *      notnull
+     *          Boolean flag that indicates whether this field is constrained
+     *          to not be set to null.
+     * @return string  DBMS specific SQL code portion that should be used to
+     *      declare the specified field.
+     * @access public
+     */
+    function getTypeDeclaration($field)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        switch ($field['type']) {
+        case 'text':
+            if (empty($field['length']) && array_key_exists('default', $field)) {
+                $field['length'] = $db->varchar_max_length;
+            }
+            $length = !empty($field['length']) ? $field['length'] : false;
+            $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
+            return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR(255)')
+                : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
+        case 'clob':
+            if (!empty($field['length'])) {
+                $length = $field['length'];
+                if ($length <= 255) {
+                    return 'TINYTEXT';
+                } elseif ($length <= 65532) {
+                    return 'TEXT';
+                } elseif ($length <= 16777215) {
+                    return 'MEDIUMTEXT';
+                }
+            }
+            return 'LONGTEXT';
+        case 'blob':
+            if (!empty($field['length'])) {
+                $length = $field['length'];
+                if ($length <= 255) {
+                    return 'TINYBLOB';
+                } elseif ($length <= 65532) {
+                    return 'BLOB';
+                } elseif ($length <= 16777215) {
+                    return 'MEDIUMBLOB';
+                }
+            }
+            return 'LONGBLOB';
+        case 'integer':
+            if (!empty($field['length'])) {
+                $length = $field['length'];
+                if ($length <= 1) {
+                    return 'TINYINT';
+                } elseif ($length == 2) {
+                    return 'SMALLINT';
+                } elseif ($length == 3) {
+                    return 'MEDIUMINT';
+                } elseif ($length == 4) {
+                    return 'INT';
+                } elseif ($length > 4) {
+                    return 'BIGINT';
+                }
+            }
+            return 'INT';
+        case 'boolean':
+            return 'TINYINT(1)';
+        case 'date':
+            return 'DATE';
+        case 'time':
+            return 'TIME';
+        case 'timestamp':
+            return 'DATETIME';
+        case 'float':
+            return 'DOUBLE';
+        case 'decimal':
+            $length = !empty($field['length']) ? $field['length'] : 18;
+            $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
+            return 'DECIMAL('.$length.','.$scale.')';
+        }
+        return '';
+    }
+
+    // }}}
+    // {{{ _getIntegerDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare an integer type
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param string  $name   name the field to be declared.
+     * @param string  $field  associative array with the name of the properties
+     *                        of the field being declared as array indexes.
+     *                        Currently, the types of supported field
+     *                        properties are as follows:
+     *
+     *                       unsigned
+     *                        Boolean flag that indicates whether the field
+     *                        should be declared as unsigned integer if
+     *                        possible.
+     *
+     *                       default
+     *                        Integer value to be used as default for this
+     *                        field.
+     *
+     *                       notnull
+     *                        Boolean flag that indicates whether this field is
+     *                        constrained to not be set to null.
+     * @return string  DBMS specific SQL code portion that should be used to
+     *                 declare the specified field.
+     * @access protected
+     */
+    function _getIntegerDeclaration($name, $field)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $default = $autoinc = '';
+        if (!empty($field['autoincrement'])) {
+            $autoinc = ' AUTO_INCREMENT PRIMARY KEY';
+        } elseif (array_key_exists('default', $field)) {
+            if ($field['default'] === '') {
+                $field['default'] = empty($field['notnull']) ? null : 0;
+            }
+            $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
+        } elseif (empty($field['notnull'])) {
+            $default = ' DEFAULT NULL';
+        }
+
+        $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
+        $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
+        $name = $db->quoteIdentifier($name, true);
+        return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc;
+    }
+
+    // }}}
+    // {{{ matchPattern()
+
+    /**
+     * build a pattern matching string
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change signature at
+     * any time until labelled as non-experimental
+     *
+     * @access public
+     *
+     * @param array $pattern even keys are strings, odd are patterns (% and _)
+     * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
+     * @param string $field optional field name that is being matched against
+     *                  (might be required when emulating ILIKE)
+     *
+     * @return string SQL pattern
+     */
+    function matchPattern($pattern, $operator = null, $field = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $match = '';
+        if (!is_null($operator)) {
+            $field = is_null($field) ? '' : $field.' ';
+            $operator = strtoupper($operator);
+            switch ($operator) {
+            // case insensitive
+            case 'ILIKE':
+                $match = $field.'LIKE ';
+                break;
+            // case sensitive
+            case 'LIKE':
+                $match = $field.'LIKE BINARY ';
+                break;
+            default:
+                return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                    'not a supported operator type:'. $operator, __FUNCTION__);
+            }
+        }
+        $match.= "'";
+        foreach ($pattern as $key => $value) {
+            if ($key % 2) {
+                $match.= $value;
+            } else {
+                $match.= $db->escapePattern($db->escape($value));
+            }
+        }
+        $match.= "'";
+        $match.= $this->patternEscapeString();
+        return $match;
+    }
+
+    // }}}
+    // {{{ _mapNativeDatatype()
+
+    /**
+     * Maps a native array description of a field to a MDB2 datatype and length
+     *
+     * @param array  $field native field description
+     * @return array containing the various possible types, length, sign, fixed
+     * @access public
+     */
+    function _mapNativeDatatype($field)
+    {
+        $db_type = strtolower($field['type']);
+        $db_type = strtok($db_type, '(), ');
+        if ($db_type == 'national') {
+            $db_type = strtok('(), ');
+        }
+        if (!empty($field['length'])) {
+            $length = strtok($field['length'], ', ');
+            $decimal = strtok(', ');
+        } else {
+            $length = strtok('(), ');
+            $decimal = strtok('(), ');
+        }
+        $type = array();
+        $unsigned = $fixed = null;
+        switch ($db_type) {
+        case 'tinyint':
+            $type[] = 'integer';
+            $type[] = 'boolean';
+            if (preg_match('/^(is|has)/', $field['name'])) {
+                $type = array_reverse($type);
+            }
+            $unsigned = preg_match('/ unsigned/i', $field['type']);
+            $length = 1;
+            break;
+        case 'smallint':
+            $type[] = 'integer';
+            $unsigned = preg_match('/ unsigned/i', $field['type']);
+            $length = 2;
+            break;
+        case 'mediumint':
+            $type[] = 'integer';
+            $unsigned = preg_match('/ unsigned/i', $field['type']);
+            $length = 3;
+            break;
+        case 'int':
+        case 'integer':
+            $type[] = 'integer';
+            $unsigned = preg_match('/ unsigned/i', $field['type']);
+            $length = 4;
+            break;
+        case 'bigint':
+            $type[] = 'integer';
+            $unsigned = preg_match('/ unsigned/i', $field['type']);
+            $length = 8;
+            break;
+        case 'tinytext':
+        case 'mediumtext':
+        case 'longtext':
+        case 'text':
+        case 'text':
+        case 'varchar':
+            $fixed = false;
+        case 'string':
+        case 'char':
+            $type[] = 'text';
+            if ($length == '1') {
+                $type[] = 'boolean';
+                if (preg_match('/^(is|has)/', $field['name'])) {
+                    $type = array_reverse($type);
+                }
+            } elseif (strstr($db_type, 'text')) {
+                $type[] = 'clob';
+                if ($decimal == 'binary') {
+                    $type[] = 'blob';
+                }
+            }
+            if ($fixed !== false) {
+                $fixed = true;
+            }
+            break;
+        case 'enum':
+            $type[] = 'text';
+            preg_match_all('/\'.+\'/U', $field['type'], $matches);
+            $length = 0;
+            $fixed = false;
+            if (is_array($matches)) {
+                foreach ($matches[0] as $value) {
+                    $length = max($length, strlen($value)-2);
+                }
+                if ($length == '1' && count($matches[0]) == 2) {
+                    $type[] = 'boolean';
+                    if (preg_match('/^(is|has)/', $field['name'])) {
+                        $type = array_reverse($type);
+                    }
+                }
+            }
+            $type[] = 'integer';
+        case 'set':
+            $fixed = false;
+            $type[] = 'text';
+            $type[] = 'integer';
+            break;
+        case 'date':
+            $type[] = 'date';
+            $length = null;
+            break;
+        case 'datetime':
+        case 'timestamp':
+            $type[] = 'timestamp';
+            $length = null;
+            break;
+        case 'time':
+            $type[] = 'time';
+            $length = null;
+            break;
+        case 'float':
+        case 'double':
+        case 'real':
+            $type[] = 'float';
+            $unsigned = preg_match('/ unsigned/i', $field['type']);
+            break;
+        case 'unknown':
+        case 'decimal':
+        case 'numeric':
+            $type[] = 'decimal';
+            $unsigned = preg_match('/ unsigned/i', $field['type']);
+            if ($decimal !== false) {
+                $length = $length.','.$decimal;
+            }
+            break;
+        case 'tinyblob':
+        case 'mediumblob':
+        case 'longblob':
+        case 'blob':
+            $type[] = 'blob';
+            $length = null;
+            break;
+        case 'binary':
+        case 'varbinary':
+            $type[] = 'blob';
+            break;
+        case 'year':
+            $type[] = 'integer';
+            $type[] = 'date';
+            $length = null;
+            break;
+        default:
+            $db =& $this->getDBInstance();
+            if (PEAR::isError($db)) {
+                return $db;
+            }
+
+            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'unknown database attribute type: '.$db_type, __FUNCTION__);
+        }
+
+        if ((int)$length <= 0) {
+            $length = null;
+        }
+
+        return array($type, $length, $unsigned, $fixed);
+    }
+
+    // }}}
+}
+
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Datatype/pgsql.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Datatype/pgsql.php
new file mode 100644 (file)
index 0000000..828cc77
--- /dev/null
@@ -0,0 +1,559 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Paul Cooper <pgc@ucecom.com>                                 |
+// +----------------------------------------------------------------------+
+//
+// $Id: pgsql.php,v 1.84 2007/03/28 16:58:54 quipo Exp $
+
+require_once 'MDB2/Driver/Datatype/Common.php';
+
+/**
+ * MDB2 PostGreSQL driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Paul Cooper <pgc@ucecom.com>
+ */
+class MDB2_Driver_Datatype_pgsql extends MDB2_Driver_Datatype_Common
+{
+    // {{{ _baseConvertResult()
+
+    /**
+     * General type conversion method
+     *
+     * @param mixed   $value refernce to a value to be converted
+     * @param string  $type  specifies which type to convert to
+     * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
+     * @return object a MDB2 error on failure
+     * @access protected
+     */
+    function _baseConvertResult($value, $type, $rtrim = true)
+    {
+        if (is_null($value)) {
+            return null;
+        }
+        switch ($type) {
+        case 'boolean':
+            return $value == 't';
+        case 'float':
+            return doubleval($value);
+        case 'date':
+            return $value;
+        case 'time':
+            return substr($value, 0, strlen('HH:MM:SS'));
+        case 'timestamp':
+            return substr($value, 0, strlen('YYYY-MM-DD HH:MM:SS'));
+        case 'blob':
+            $value = pg_unescape_bytea($value);
+            return parent::_baseConvertResult($value, $type, $rtrim);
+        }
+        return parent::_baseConvertResult($value, $type, $rtrim);
+    }
+
+    // }}}
+    // {{{ getTypeDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare an text type
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param array $field  associative array with the name of the properties
+     *      of the field being declared as array indexes. Currently, the types
+     *      of supported field properties are as follows:
+     *
+     *      length
+     *          Integer value that determines the maximum length of the text
+     *          field. If this argument is missing the field should be
+     *          declared to have the longest length allowed by the DBMS.
+     *
+     *      default
+     *          Text value to be used as default for this field.
+     *
+     *      notnull
+     *          Boolean flag that indicates whether this field is constrained
+     *          to not be set to null.
+     * @return string  DBMS specific SQL code portion that should be used to
+     *      declare the specified field.
+     * @access public
+     */
+    function getTypeDeclaration($field)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        switch ($field['type']) {
+        case 'text':
+            $length = !empty($field['length'])
+                ? $field['length'] : $db->options['default_text_field_length'];
+            $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
+            return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
+                : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
+        case 'clob':
+            return 'TEXT';
+        case 'blob':
+            return 'BYTEA';
+        case 'integer':
+            if (!empty($field['autoincrement'])) {
+                if (!empty($field['length'])) {
+                    $length = $field['length'];
+                    if ($length > 4) {
+                        return 'BIGSERIAL PRIMARY KEY';
+                    }
+                }
+                return 'SERIAL PRIMARY KEY';
+            }
+            if (!empty($field['length'])) {
+                $length = $field['length'];
+                if ($length <= 2) {
+                    return 'SMALLINT';
+                } elseif ($length == 3 || $length == 4) {
+                    return 'INT';
+                } elseif ($length > 4) {
+                    return 'BIGINT';
+                }
+            }
+            return 'INT';
+        case 'boolean':
+            return 'BOOLEAN';
+        case 'date':
+            return 'DATE';
+        case 'time':
+            return 'TIME without time zone';
+        case 'timestamp':
+            return 'TIMESTAMP without time zone';
+        case 'float':
+            return 'FLOAT8';
+        case 'decimal':
+            $length = !empty($field['length']) ? $field['length'] : 18;
+            $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
+            return 'NUMERIC('.$length.','.$scale.')';
+        }
+    }
+
+    // }}}
+    // {{{ _getIntegerDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare an integer type
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param string $name name the field to be declared.
+     * @param array $field associative array with the name of the properties
+     *       of the field being declared as array indexes. Currently, the types
+     *       of supported field properties are as follows:
+     *
+     *       unsigned
+     *           Boolean flag that indicates whether the field should be
+     *           declared as unsigned integer if possible.
+     *
+     *       default
+     *           Integer value to be used as default for this field.
+     *
+     *       notnull
+     *           Boolean flag that indicates whether this field is constrained
+     *           to not be set to null.
+     * @return string DBMS specific SQL code portion that should be used to
+     *       declare the specified field.
+     * @access protected
+     */
+    function _getIntegerDeclaration($name, $field)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        if (!empty($field['unsigned'])) {
+            $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
+        }
+        if (!empty($field['autoincrement'])) {
+            $name = $db->quoteIdentifier($name, true);
+            return $name.' '.$this->getTypeDeclaration($field);
+        }
+        $default = '';
+        if (array_key_exists('default', $field)) {
+            if ($field['default'] === '') {
+                $field['default'] = empty($field['notnull']) ? null : 0;
+            }
+            $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
+        } elseif (empty($field['notnull'])) {
+            $default = ' DEFAULT NULL';
+        }
+
+        $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
+        $name = $db->quoteIdentifier($name, true);
+        return $name.' '.$this->getTypeDeclaration($field).$default.$notnull;
+    }
+
+    // }}}
+    // {{{ _quoteCLOB()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
+     * @return string text string that represents the given argument value in
+     *      a DBMS specific format.
+     * @access protected
+     */
+    function _quoteCLOB($value, $quote, $escape_wildcards)
+    {
+        return $this->_quoteText($value, $quote, $escape_wildcards);
+    }
+
+    // }}}
+    // {{{ _quoteBLOB()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
+     * @return string text string that represents the given argument value in
+     *      a DBMS specific format.
+     * @access protected
+     */
+    function _quoteBLOB($value, $quote, $escape_wildcards)
+    {
+        if (!$quote) {
+            return $value;
+        }
+        if (version_compare(PHP_VERSION, '5.2.0RC6', '>=')) {
+            $db =& $this->getDBInstance();
+            if (PEAR::isError($db)) {
+                return $db;
+            }
+            $connection = $db->getConnection();
+            if (PEAR::isError($connection)) {
+                return $connection;
+            }
+            $value = @pg_escape_bytea($connection, $value);
+        } else {
+            $value = @pg_escape_bytea($value);
+        }
+        return "'".$value."'";
+    }
+
+    // }}}
+    // {{{ _quoteBoolean()
+
+    /**
+     * Convert a text value into a DBMS specific format that is suitable to
+     * compose query statements.
+     *
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
+     * @return string text string that represents the given argument value in
+     *       a DBMS specific format.
+     * @access protected
+     */
+    function _quoteBoolean($value, $quote, $escape_wildcards)
+    {
+        $value = $value ? 't' : 'f';
+        if (!$quote) {
+            return $value;
+        }
+        return "'".$value."'";
+    }
+
+    // }}}
+    // {{{ matchPattern()
+
+    /**
+     * build a pattern matching string
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change signature at
+     * any time until labelled as non-experimental
+     *
+     * @access public
+     *
+     * @param array $pattern even keys are strings, odd are patterns (% and _)
+     * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
+     * @param string $field optional field name that is being matched against
+     *                  (might be required when emulating ILIKE)
+     *
+     * @return string SQL pattern
+     */
+    function matchPattern($pattern, $operator = null, $field = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $match = '';
+        if (!is_null($operator)) {
+            $field = is_null($field) ? '' : $field.' ';
+            $operator = strtoupper($operator);
+            switch ($operator) {
+            // case insensitive
+            case 'ILIKE':
+                $match = $field.'ILIKE ';
+                break;
+            // case sensitive
+            case 'LIKE':
+                $match = $field.'LIKE ';
+                break;
+            default:
+                return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                    'not a supported operator type:'. $operator, __FUNCTION__);
+            }
+        }
+        $match.= "'";
+        foreach ($pattern as $key => $value) {
+            if ($key % 2) {
+                $match.= $value;
+            } else {
+                $match.= $db->escapePattern($db->escape($value));
+            }
+        }
+        $match.= "'";
+        $match.= $this->patternEscapeString();
+        return $match;
+    }
+
+    // }}}
+    // {{{ patternEscapeString()
+
+    /**
+     * build string to define escape pattern string
+     *
+     * @access public
+     *
+     *
+     * @return string define escape pattern
+     */
+    function patternEscapeString()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+        return ' ESCAPE '.$this->quote($db->string_quoting['escape_pattern']);
+    }
+
+    // }}}
+    // {{{ _mapNativeDatatype()
+
+    /**
+     * Maps a native array description of a field to a MDB2 datatype and length
+     *
+     * @param array  $field native field description
+     * @return array containing the various possible types, length, sign, fixed
+     * @access public
+     */
+    function _mapNativeDatatype($field)
+    {
+        $db_type = strtolower($field['type']);
+        $length = $field['length'];
+        $type = array();
+        $unsigned = $fixed = null;
+        switch ($db_type) {
+        case 'smallint':
+        case 'int2':
+            $type[] = 'integer';
+            $unsigned = false;
+            $length = 2;
+            if ($length == '2') {
+                $type[] = 'boolean';
+                if (preg_match('/^(is|has)/', $field['name'])) {
+                    $type = array_reverse($type);
+                }
+            }
+            break;
+        case 'int':
+        case 'int4':
+        case 'integer':
+        case 'serial':
+        case 'serial4':
+            $type[] = 'integer';
+            $unsigned = false;
+            $length = 4;
+            break;
+        case 'bigint':
+        case 'int8':
+        case 'bigserial':
+        case 'serial8':
+            $type[] = 'integer';
+            $unsigned = false;
+            $length = 8;
+            break;
+        case 'bool':
+        case 'boolean':
+            $type[] = 'boolean';
+            $length = null;
+            break;
+        case 'text':
+        case 'varchar':
+            $fixed = false;
+        case 'unknown':
+        case 'char':
+        case 'bpchar':
+            $type[] = 'text';
+            if ($length == '1') {
+                $type[] = 'boolean';
+                if (preg_match('/^(is|has)/', $field['name'])) {
+                    $type = array_reverse($type);
+                }
+            } elseif (strstr($db_type, 'text')) {
+                $type[] = 'clob';
+            }
+            if ($fixed !== false) {
+                $fixed = true;
+            }
+            break;
+        case 'date':
+            $type[] = 'date';
+            $length = null;
+            break;
+        case 'datetime':
+        case 'timestamp':
+            $type[] = 'timestamp';
+            $length = null;
+            break;
+        case 'time':
+            $type[] = 'time';
+            $length = null;
+            break;
+        case 'float':
+        case 'float8':
+        case 'double':
+        case 'real':
+            $type[] = 'float';
+            break;
+        case 'decimal':
+        case 'money':
+        case 'numeric':
+            $type[] = 'decimal';
+            if ($field['scale']) {
+                $length = $length.','.$field['scale'];
+            }
+            break;
+        case 'tinyblob':
+        case 'mediumblob':
+        case 'longblob':
+        case 'blob':
+        case 'bytea':
+            $type[] = 'blob';
+            $length = null;
+            break;
+        case 'oid':
+            $type[] = 'blob';
+            $type[] = 'clob';
+            $length = null;
+            break;
+        case 'year':
+            $type[] = 'integer';
+            $type[] = 'date';
+            $length = null;
+            break;
+        default:
+            $db =& $this->getDBInstance();
+            if (PEAR::isError($db)) {
+                return $db;
+            }
+            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'unknown database attribute type: '.$db_type, __FUNCTION__);
+        }
+
+        if ((int)$length <= 0) {
+            $length = null;
+        }
+
+        return array($type, $length, $unsigned, $fixed);
+    }
+
+    // }}}
+    // {{{ mapPrepareDatatype()
+
+    /**
+     * Maps an mdb2 datatype to native prepare type
+     *
+     * @param string $type
+     * @return string
+     * @access public
+     */
+    function mapPrepareDatatype($type)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        if (!empty($db->options['datatype_map'][$type])) {
+            $type = $db->options['datatype_map'][$type];
+            if (!empty($db->options['datatype_map_callback'][$type])) {
+                $parameter = array('type' => $type);
+                return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
+            }
+        }
+
+        switch ($type) {
+            case 'integer':
+                return 'int';
+            case 'boolean':
+                return 'bool';
+            case 'decimal':
+            case 'float':
+                return 'numeric';
+            case 'clob':
+                return 'text';
+            case 'blob':
+                return 'bytea';
+            default:
+                break;
+        }
+        return $type;
+    }
+    // }}}
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Datatype/sqlite.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Datatype/sqlite.php
new file mode 100644 (file)
index 0000000..51d9562
--- /dev/null
@@ -0,0 +1,395 @@
+<?php
+// vim: set et ts=4 sw=4 fdm=marker:
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: sqlite.php,v 1.62 2007/03/28 16:58:54 quipo Exp $
+//
+
+require_once 'MDB2/Driver/Datatype/Common.php';
+
+/**
+ * MDB2 SQLite driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_Datatype_sqlite extends MDB2_Driver_Datatype_Common
+{
+    // }}}
+    // {{{ getTypeDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare an text type
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param array $field  associative array with the name of the properties
+     *      of the field being declared as array indexes. Currently, the types
+     *      of supported field properties are as follows:
+     *
+     *      length
+     *          Integer value that determines the maximum length of the text
+     *          field. If this argument is missing the field should be
+     *          declared to have the longest length allowed by the DBMS.
+     *
+     *      default
+     *          Text value to be used as default for this field.
+     *
+     *      notnull
+     *          Boolean flag that indicates whether this field is constrained
+     *          to not be set to null.
+     * @return string  DBMS specific SQL code portion that should be used to
+     *      declare the specified field.
+     * @access public
+     */
+    function getTypeDeclaration($field)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        switch ($field['type']) {
+        case 'text':
+            $length = !empty($field['length'])
+                ? $field['length'] : false;
+            $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
+            return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
+                : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
+        case 'clob':
+            if (!empty($field['length'])) {
+                $length = $field['length'];
+                if ($length <= 255) {
+                    return 'TINYTEXT';
+                } elseif ($length <= 65532) {
+                    return 'TEXT';
+                } elseif ($length <= 16777215) {
+                    return 'MEDIUMTEXT';
+                }
+            }
+            return 'LONGTEXT';
+        case 'blob':
+            if (!empty($field['length'])) {
+                $length = $field['length'];
+                if ($length <= 255) {
+                    return 'TINYBLOB';
+                } elseif ($length <= 65532) {
+                    return 'BLOB';
+                } elseif ($length <= 16777215) {
+                    return 'MEDIUMBLOB';
+                }
+            }
+            return 'LONGBLOB';
+        case 'integer':
+            if (!empty($field['length'])) {
+                $length = $field['length'];
+                if ($length <= 2) {
+                    return 'SMALLINT';
+                } elseif ($length == 3 || $length == 4) {
+                    return 'INTEGER';
+                } elseif ($length > 4) {
+                    return 'BIGINT';
+                }
+            }
+            return 'INTEGER';
+        case 'boolean':
+            return 'BOOLEAN';
+        case 'date':
+            return 'DATE';
+        case 'time':
+            return 'TIME';
+        case 'timestamp':
+            return 'DATETIME';
+        case 'float':
+            return 'DOUBLE'.($db->options['fixed_float'] ? '('.
+                ($db->options['fixed_float']+2).','.$db->options['fixed_float'].')' : '');
+        case 'decimal':
+            $length = !empty($field['length']) ? $field['length'] : 18;
+            $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
+            return 'DECIMAL('.$length.','.$scale.')';
+        }
+        return '';
+    }
+
+    // }}}
+    // {{{ _getIntegerDeclaration()
+
+    /**
+     * Obtain DBMS specific SQL code portion needed to declare an integer type
+     * field to be used in statements like CREATE TABLE.
+     *
+     * @param string  $name   name the field to be declared.
+     * @param string  $field  associative array with the name of the properties
+     *                        of the field being declared as array indexes.
+     *                        Currently, the types of supported field
+     *                        properties are as follows:
+     *
+     *                       unsigned
+     *                        Boolean flag that indicates whether the field
+     *                        should be declared as unsigned integer if
+     *                        possible.
+     *
+     *                       default
+     *                        Integer value to be used as default for this
+     *                        field.
+     *
+     *                       notnull
+     *                        Boolean flag that indicates whether this field is
+     *                        constrained to not be set to null.
+     * @return string  DBMS specific SQL code portion that should be used to
+     *                 declare the specified field.
+     * @access protected
+     */
+    function _getIntegerDeclaration($name, $field)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $default = $autoinc = '';
+        if (!empty($field['autoincrement'])) {
+            $autoinc = ' PRIMARY KEY';
+        } elseif (array_key_exists('default', $field)) {
+            if ($field['default'] === '') {
+                $field['default'] = empty($field['notnull']) ? null : 0;
+            }
+            $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
+        } elseif (empty($field['notnull'])) {
+            $default = ' DEFAULT NULL';
+        }
+
+        $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
+        $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
+        $name = $db->quoteIdentifier($name, true);
+        return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc;
+    }
+
+    // }}}
+    // {{{ matchPattern()
+
+    /**
+     * build a pattern matching string
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change signature at
+     * any time until labelled as non-experimental
+     *
+     * @access public
+     *
+     * @param array $pattern even keys are strings, odd are patterns (% and _)
+     * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
+     * @param string $field optional field name that is being matched against
+     *                  (might be required when emulating ILIKE)
+     *
+     * @return string SQL pattern
+     */
+    function matchPattern($pattern, $operator = null, $field = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $match = '';
+        if (!is_null($operator)) {
+            $field = is_null($field) ? '' : $field.' ';
+            $operator = strtoupper($operator);
+            switch ($operator) {
+            // case insensitive
+            case 'ILIKE':
+                $match = $field.'LIKE ';
+                break;
+            // case sensitive
+            case 'LIKE':
+                $match = $field.'LIKE ';
+                break;
+            default:
+                return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                    'not a supported operator type:'. $operator, __FUNCTION__);
+            }
+        }
+        $match.= "'";
+        foreach ($pattern as $key => $value) {
+            if ($key % 2) {
+                $match.= $value;
+            } else {
+                $match.= $db->escapePattern($db->escape($value));
+            }
+        }
+        $match.= "'";
+        $match.= $this->patternEscapeString();
+        return $match;
+    }
+
+    // }}}
+    // {{{ _mapNativeDatatype()
+
+    /**
+     * Maps a native array description of a field to a MDB2 datatype and length
+     *
+     * @param array  $field native field description
+     * @return array containing the various possible types, length, sign, fixed
+     * @access public
+     */
+    function _mapNativeDatatype($field)
+    {
+        $db_type = strtolower($field['type']);
+        $length = !empty($field['length']) ? $field['length'] : null;
+        $unsigned = !empty($field['unsigned']) ? $field['unsigned'] : null;
+        $fixed = null;
+        $type = array();
+        switch ($db_type) {
+        case 'boolean':
+            $type[] = 'boolean';
+            break;
+        case 'tinyint':
+            $type[] = 'integer';
+            $type[] = 'boolean';
+            if (preg_match('/^(is|has)/', $field['name'])) {
+                $type = array_reverse($type);
+            }
+            $unsigned = preg_match('/ unsigned/i', $field['type']);
+            $length = 1;
+            break;
+        case 'smallint':
+            $type[] = 'integer';
+            $unsigned = preg_match('/ unsigned/i', $field['type']);
+            $length = 2;
+            break;
+        case 'mediumint':
+            $type[] = 'integer';
+            $unsigned = preg_match('/ unsigned/i', $field['type']);
+            $length = 3;
+            break;
+        case 'int':
+        case 'integer':
+        case 'serial':
+            $type[] = 'integer';
+            $unsigned = preg_match('/ unsigned/i', $field['type']);
+            $length = 4;
+            break;
+        case 'bigint':
+        case 'bigserial':
+            $type[] = 'integer';
+            $unsigned = preg_match('/ unsigned/i', $field['type']);
+            $length = 8;
+            break;
+        case 'clob':
+        case 'tinytext':
+        case 'mediumtext':
+        case 'longtext':
+        case 'text':
+        case 'varchar':
+        case 'varchar2':
+            $fixed = false;
+        case 'char':
+            $type[] = 'text';
+            if ($length == '1') {
+                $type[] = 'boolean';
+                if (preg_match('/^(is|has)/', $field['name'])) {
+                    $type = array_reverse($type);
+                }
+            } elseif (strstr($db_type, 'text')) {
+                $type[] = 'clob';
+            }
+            if ($fixed !== false) {
+                $fixed = true;
+            }
+            break;
+        case 'date':
+            $type[] = 'date';
+            $length = null;
+            break;
+        case 'datetime':
+        case 'timestamp':
+            $type[] = 'timestamp';
+            $length = null;
+            break;
+        case 'time':
+            $type[] = 'time';
+            $length = null;
+            break;
+        case 'float':
+        case 'double':
+        case 'real':
+            $type[] = 'float';
+            break;
+        case 'decimal':
+        case 'numeric':
+            $type[] = 'decimal';
+            $length = $length.','.$field['decimal'];
+            break;
+        case 'tinyblob':
+        case 'mediumblob':
+        case 'longblob':
+        case 'blob':
+            $type[] = 'blob';
+            $length = null;
+            break;
+        case 'year':
+            $type[] = 'integer';
+            $type[] = 'date';
+            $length = null;
+            break;
+        default:
+            $db =& $this->getDBInstance();
+            if (PEAR::isError($db)) {
+                return $db;
+            }
+
+            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'unknown database attribute type: '.$db_type, __FUNCTION__);
+        }
+
+        if ((int)$length <= 0) {
+            $length = null;
+        }
+
+        return array($type, $length, $unsigned, $fixed);
+    }
+}
+
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Function/Common.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Function/Common.php
new file mode 100644 (file)
index 0000000..3e582c6
--- /dev/null
@@ -0,0 +1,231 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: Common.php,v 1.17 2007/01/12 11:29:12 quipo Exp $
+//
+
+/**
+ * @package  MDB2
+ * @category Database
+ * @author   Lukas Smith <smith@pooteeweet.org>
+ */
+
+/**
+ * Base class for the function modules that is extended by each MDB2 driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_Function_Common extends MDB2_Module_Common
+{
+    // {{{ executeStoredProc()
+
+    /**
+     * Execute a stored procedure and return any results
+     *
+     * @param string $name string that identifies the function to execute
+     * @param mixed  $params  array that contains the paramaters to pass the stored proc
+     * @param mixed   $types  array that contains the types of the columns in
+     *                        the result set
+     * @param mixed $result_class string which specifies which result class to use
+     * @param mixed $result_wrap_class string which specifies which class to wrap results in
+     * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function &executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+        return $error;
+    }
+
+    // }}}
+    // {{{ functionTable()
+
+    /**
+     * return string for internal table used when calling only a function
+     *
+     * @return string for internal table used when calling only a function
+     * @access public
+     */
+    function functionTable()
+    {
+        return '';
+    }
+
+    // }}}
+    // {{{ now()
+
+    /**
+     * Return string to call a variable with the current timestamp inside an SQL statement
+     * There are three special variables for current date and time:
+     * - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
+     * - CURRENT_DATE (date, DATE type)
+     * - CURRENT_TIME (time, TIME type)
+     *
+     * @return string to call a variable with the current timestamp
+     * @access public
+     */
+    function now($type = 'timestamp')
+    {
+        switch ($type) {
+        case 'time':
+            return 'CURRENT_TIME';
+        case 'date':
+            return 'CURRENT_DATE';
+        case 'timestamp':
+        default:
+            return 'CURRENT_TIMESTAMP';
+        }
+    }
+
+    // }}}
+    // {{{ substring()
+
+    /**
+     * return string to call a function to get a substring inside an SQL statement
+     *
+     * @return string to call a function to get a substring
+     * @access public
+     */
+    function substring($value, $position = 1, $length = null)
+    {
+        if (!is_null($length)) {
+            return "SUBSTRING($value FROM $position FOR $length)";
+        }
+        return "SUBSTRING($value FROM $position)";
+    }
+
+    // }}}
+    // {{{ concat()
+
+    /**
+     * Returns string to concatenate two or more string parameters
+     *
+     * @param string $value1
+     * @param string $value2
+     * @param string $values...
+     * @return string to concatenate two strings
+     * @access public
+     */
+    function concat($value1, $value2)
+    {
+        $args = func_get_args();
+        return "(".implode(' || ', $args).")";
+    }
+
+    // }}}
+    // {{{ random()
+
+    /**
+     * return string to call a function to get random value inside an SQL statement
+     *
+     * @return return string to generate float between 0 and 1
+     * @access public
+     */
+    function random()
+    {
+        return 'RAND()';
+    }
+
+    // }}}
+    // {{{ lower()
+
+    /**
+     * return string to call a function to lower the case of an expression
+     *
+     * @param string $expression
+     * @return return string to lower case of an expression
+     * @access public
+     */
+    function lower($expression)
+    {
+        return "LOWER($expression)";
+    }
+
+    // }}}
+    // {{{ upper()
+
+    /**
+     * return string to call a function to upper the case of an expression
+     *
+     * @param string $expression
+     * @return return string to upper case of an expression
+     * @access public
+     */
+    function upper($expression)
+    {
+        return "UPPER($expression)";
+    }
+
+    // }}}
+    // {{{ guid()
+
+    /**
+     * Returns global unique identifier
+     *
+     * @return string to get global unique identifier
+     * @access public
+     */
+    function guid()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+        return $error;
+    }
+
+    // }}}
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Function/mysql.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Function/mysql.php
new file mode 100644 (file)
index 0000000..90dea81
--- /dev/null
@@ -0,0 +1,120 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: mysql.php,v 1.11 2007/01/12 11:29:12 quipo Exp $
+//
+
+require_once 'MDB2/Driver/Function/Common.php';
+
+/**
+ * MDB2 MySQL driver for the function modules
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_Function_mysql extends MDB2_Driver_Function_Common
+{
+     // }}}
+    // {{{ executeStoredProc()
+
+    /**
+     * Execute a stored procedure and return any results
+     *
+     * @param string $name string that identifies the function to execute
+     * @param mixed  $params  array that contains the paramaters to pass the stored proc
+     * @param mixed   $types  array that contains the types of the columns in
+     *                        the result set
+     * @param mixed $result_class string which specifies which result class to use
+     * @param mixed $result_wrap_class string which specifies which class to wrap results in
+     * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function &executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = 'CALL '.$name;
+        $query .= $params ? '('.implode(', ', $params).')' : '()';
+        return $db->query($query, $types, $result_class, $result_wrap_class);
+    }
+
+    // }}}
+    // {{{ concat()
+
+    /**
+     * Returns string to concatenate two or more string parameters
+     *
+     * @param string $value1
+     * @param string $value2
+     * @param string $values...
+     * @return string to concatenate two strings
+     * @access public
+     **/
+    function concat($value1, $value2)
+    {
+        $args = func_get_args();
+        return "CONCAT(".implode(', ', $args).")";
+    }
+
+    // }}}
+    // {{{ guid()
+
+    /**
+     * Returns global unique identifier
+     *
+     * @return string to get global unique identifier
+     * @access public
+     */
+    function guid()
+    {
+        return 'UUID()';
+    }
+
+    // }}}
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Function/pgsql.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Function/pgsql.php
new file mode 100644 (file)
index 0000000..df1d455
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Paul Cooper <pgc@ucecom.com>                                 |
+// +----------------------------------------------------------------------+
+//
+// $Id: pgsql.php,v 1.9 2006/06/12 21:48:43 lsmith Exp $
+
+require_once 'MDB2/Driver/Function/Common.php';
+
+/**
+ * MDB2 MySQL driver for the function modules
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_Function_pgsql extends MDB2_Driver_Function_Common
+{
+    // {{{ executeStoredProc()
+
+    /**
+     * Execute a stored procedure and return any results
+     *
+     * @param string $name string that identifies the function to execute
+     * @param mixed  $params  array that contains the paramaters to pass the stored proc
+     * @param mixed   $types  array that contains the types of the columns in
+     *                        the result set
+     * @param mixed $result_class string which specifies which result class to use
+     * @param mixed $result_wrap_class string which specifies which class to wrap results in
+     * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function &executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = 'SELECT * FROM '.$name;
+        $query .= $params ? '('.implode(', ', $params).')' : '()';
+        return $db->query($query, $types, $result_class, $result_wrap_class);
+    }
+    // }}}
+    // {{{ random()
+
+    /**
+     * return string to call a function to get random value inside an SQL statement
+     *
+     * @return return string to generate float between 0 and 1
+     * @access public
+     */
+    function random()
+    {
+        return 'RANDOM()';
+    }
+
+    // }}}
+}
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Function/sqlite.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Function/sqlite.php
new file mode 100644 (file)
index 0000000..3a4960b
--- /dev/null
@@ -0,0 +1,125 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: sqlite.php,v 1.8 2006/06/13 22:55:55 lsmith Exp $
+//
+
+require_once 'MDB2/Driver/Function/Common.php';
+
+/**
+ * MDB2 SQLite driver for the function modules
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_Function_sqlite extends MDB2_Driver_Function_Common
+{
+    // {{{ constructor
+
+    /**
+     * Constructor
+     */
+    function __construct($db_index)
+    {
+        parent::__construct($db_index);
+        // create all sorts of UDFs
+    }
+
+    // {{{ now()
+
+    /**
+     * Return string to call a variable with the current timestamp inside an SQL statement
+     * There are three special variables for current date and time.
+     *
+     * @return string to call a variable with the current timestamp
+     * @access public
+     */
+    function now($type = 'timestamp')
+    {
+        switch ($type) {
+        case 'time':
+            return 'time(\'now\')';
+        case 'date':
+            return 'date(\'now\')';
+        case 'timestamp':
+        default:
+            return 'datetime(\'now\')';
+        }
+    }
+
+    // }}}
+    // {{{ substring()
+
+    /**
+     * return string to call a function to get a substring inside an SQL statement
+     *
+     * @return string to call a function to get a substring
+     * @access public
+     */
+    function substring($value, $position = 1, $length = null)
+    {
+        if (!is_null($length)) {
+            return "substr($value,$position,$length)";
+        }
+        return "substr($value,$position,length($value))";
+    }
+
+    // }}}
+    // {{{ random()
+
+    /**
+     * return string to call a function to get random value inside an SQL statement
+     *
+     * @return return string to generate float between 0 and 1
+     * @access public
+     */
+    function random()
+    {
+        return '((RANDOM()+2147483648)/4294967296)';
+    }
+
+    // }}}
+}
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Manager/Common.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Manager/Common.php
new file mode 100644 (file)
index 0000000..89b7078
--- /dev/null
@@ -0,0 +1,864 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: Common.php,v 1.62 2007/03/28 16:39:55 quipo Exp $
+//
+
+/**
+ * @package  MDB2
+ * @category Database
+ * @author   Lukas Smith <smith@pooteeweet.org>
+ */
+
+/**
+ * Base class for the management modules that is extended by each MDB2 driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_Manager_Common extends MDB2_Module_Common
+{
+    // {{{ getFieldDeclarationList()
+
+    /**
+     * Get declaration of a number of field in bulk
+     *
+     * @param array $fields  a multidimensional associative array.
+     *      The first dimension determines the field name, while the second
+     *      dimension is keyed with the name of the properties
+     *      of the field being declared as array indexes. Currently, the types
+     *      of supported field properties are as follows:
+     *
+     *      default
+     *          Boolean value to be used as default for this field.
+     *
+     *      notnull
+     *          Boolean flag that indicates whether this field is constrained
+     *          to not be set to null.
+     *
+     * @return mixed string on success, a MDB2 error on failure
+     * @access public
+     */
+    function getFieldDeclarationList($fields)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        if (!is_array($fields) || empty($fields)) {
+            return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                'missing any fields', __FUNCTION__);
+        }
+        foreach ($fields as $field_name => $field) {
+            $query = $db->getDeclaration($field['type'], $field_name, $field);
+            if (PEAR::isError($query)) {
+                return $query;
+            }
+            $query_fields[] = $query;
+        }
+        return implode(', ', $query_fields);
+    }
+
+    // }}}
+    // {{{ _fixSequenceName()
+
+    /**
+     * Removes any formatting in an sequence name using the 'seqname_format' option
+     *
+     * @param string $sqn string that containts name of a potential sequence
+     * @param bool $check if only formatted sequences should be returned
+     * @return string name of the sequence with possible formatting removed
+     * @access protected
+     */
+    function _fixSequenceName($sqn, $check = false)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $seq_pattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $db->options['seqname_format']).'$/i';
+        $seq_name = preg_replace($seq_pattern, '\\1', $sqn);
+        if ($seq_name && !strcasecmp($sqn, $db->getSequenceName($seq_name))) {
+            return $seq_name;
+        }
+        if ($check) {
+            return false;
+        }
+        return $sqn;
+    }
+
+    // }}}
+    // {{{ _fixIndexName()
+
+    /**
+     * Removes any formatting in an index name using the 'idxname_format' option
+     *
+     * @param string $idx string that containts name of anl index
+     * @return string name of the index with possible formatting removed
+     * @access protected
+     */
+    function _fixIndexName($idx)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $idx_pattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $db->options['idxname_format']).'$/i';
+        $idx_name = preg_replace($idx_pattern, '\\1', $idx);
+        if ($idx_name && !strcasecmp($idx, $db->getIndexName($idx_name))) {
+            return $idx_name;
+        }
+        return $idx;
+    }
+
+    // }}}
+    // {{{ createDatabase()
+
+    /**
+     * create a new database
+     *
+     * @param string $name name of the database that should be created
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createDatabase($database)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ dropDatabase()
+
+    /**
+     * drop an existing database
+     *
+     * @param string $name name of the database that should be dropped
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropDatabase($database)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ _getCreateTableQuery()
+
+    /**
+     * Create a basic SQL query for a new table creation
+     * @param string $name   Name of the database that should be created
+     * @param array $fields  Associative array that contains the definition of each field of the new table
+     * @param array $options  An associative array of table options
+     * @return mixed string (the SQL query) on success, a MDB2 error on failure
+     * @see createTable()
+     */
+    function _getCreateTableQuery($name, $fields, $options = array())
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        if (!$name) {
+            return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
+                'no valid table name specified', __FUNCTION__);
+        }
+        if (empty($fields)) {
+            return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
+                'no fields specified for table "'.$name.'"', __FUNCTION__);
+        }
+        $query_fields = $this->getFieldDeclarationList($fields);
+        if (PEAR::isError($query_fields)) {
+            return $query_fields;
+        }
+        if (!empty($options['primary'])) {
+            $query_fields.= ', PRIMARY KEY ('.implode(', ', array_keys($options['primary'])).')';
+        }
+
+        $name = $db->quoteIdentifier($name, true);
+        $result = 'CREATE ';
+        if (!empty($options['temporary'])) {
+            $result .= $this->_getTemporaryTableQuery();
+        }
+        $result .= " TABLE $name ($query_fields)";
+        return $result;
+    }
+
+    // }}}
+    // {{{ _getTemporaryTableQuery()
+
+    /**
+     * A method to return the required SQL string that fits between CREATE ... TABLE
+     * to create the table as a temporary table.
+     *
+     * Should be overridden in driver classes to return the correct string for the
+     * specific database type.
+     *
+     * The default is to return the string "TEMPORARY" - this will result in a
+     * SQL error for any database that does not support temporary tables, or that
+     * requires a different SQL command from "CREATE TEMPORARY TABLE".
+     *
+     * @return string The string required to be placed between "CREATE" and "TABLE"
+     *                to generate a temporary table, if possible.
+     */
+    function _getTemporaryTableQuery()
+    {
+        return 'TEMPORARY';
+    }
+
+    // }}}
+    // {{{ createTable()
+
+    /**
+     * create a new table
+     *
+     * @param string $name   Name of the database that should be created
+     * @param array $fields  Associative array that contains the definition of each field of the new table
+     *                       The indexes of the array entries are the names of the fields of the table an
+     *                       the array entry values are associative arrays like those that are meant to be
+     *                       passed with the field definitions to get[Type]Declaration() functions.
+     *                          array(
+     *                              'id' => array(
+     *                                  'type' => 'integer',
+     *                                  'unsigned' => 1
+     *                                  'notnull' => 1
+     *                                  'default' => 0
+     *                              ),
+     *                              'name' => array(
+     *                                  'type' => 'text',
+     *                                  'length' => 12
+     *                              ),
+     *                              'password' => array(
+     *                                  'type' => 'text',
+     *                                  'length' => 12
+     *                              )
+     *                          );
+     * @param array $options  An associative array of table options:
+     *                          array(
+     *                              'comment' => 'Foo',
+     *                              'temporary' => true|false,
+     *                          );
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createTable($name, $fields, $options = array())
+    {
+        $query = $this->_getCreateTableQuery($name, $fields, $options);
+        if (PEAR::isError($query)) {
+            return $query;
+        }
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+        return $db->exec($query);
+    }
+
+    // }}}
+    // {{{ dropTable()
+
+    /**
+     * drop an existing table
+     *
+     * @param string $name name of the table that should be dropped
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropTable($name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $name = $db->quoteIdentifier($name, true);
+        return $db->exec("DROP TABLE $name");
+    }
+
+    // }}}
+    // {{{ alterTable()
+
+    /**
+     * alter an existing table
+     *
+     * @param string $name         name of the table that is intended to be changed.
+     * @param array $changes     associative array that contains the details of each type
+     *                             of change that is intended to be performed. The types of
+     *                             changes that are currently supported are defined as follows:
+     *
+     *                             name
+     *
+     *                                New name for the table.
+     *
+     *                            add
+     *
+     *                                Associative array with the names of fields to be added as
+     *                                 indexes of the array. The value of each entry of the array
+     *                                 should be set to another associative array with the properties
+     *                                 of the fields to be added. The properties of the fields should
+     *                                 be the same as defined by the MDB2 parser.
+     *
+     *
+     *                            remove
+     *
+     *                                Associative array with the names of fields to be removed as indexes
+     *                                 of the array. Currently the values assigned to each entry are ignored.
+     *                                 An empty array should be used for future compatibility.
+     *
+     *                            rename
+     *
+     *                                Associative array with the names of fields to be renamed as indexes
+     *                                 of the array. The value of each entry of the array should be set to
+     *                                 another associative array with the entry named name with the new
+     *                                 field name and the entry named Declaration that is expected to contain
+     *                                 the portion of the field declaration already in DBMS specific SQL code
+     *                                 as it is used in the CREATE TABLE statement.
+     *
+     *                            change
+     *
+     *                                Associative array with the names of the fields to be changed as indexes
+     *                                 of the array. Keep in mind that if it is intended to change either the
+     *                                 name of a field and any other properties, the change array entries
+     *                                 should have the new names of the fields as array indexes.
+     *
+     *                                The value of each entry of the array should be set to another associative
+     *                                 array with the properties of the fields to that are meant to be changed as
+     *                                 array entries. These entries should be assigned to the new values of the
+     *                                 respective properties. The properties of the fields should be the same
+     *                                 as defined by the MDB2 parser.
+     *
+     *                            Example
+     *                                array(
+     *                                    'name' => 'userlist',
+     *                                    'add' => array(
+     *                                        'quota' => array(
+     *                                            'type' => 'integer',
+     *                                            'unsigned' => 1
+     *                                        )
+     *                                    ),
+     *                                    'remove' => array(
+     *                                        'file_limit' => array(),
+     *                                        'time_limit' => array()
+     *                                    ),
+     *                                    'change' => array(
+     *                                        'name' => array(
+     *                                            'length' => '20',
+     *                                            'definition' => array(
+     *                                                'type' => 'text',
+     *                                                'length' => 20,
+     *                                            ),
+     *                                        )
+     *                                    ),
+     *                                    'rename' => array(
+     *                                        'sex' => array(
+     *                                            'name' => 'gender',
+     *                                            'definition' => array(
+     *                                                'type' => 'text',
+     *                                                'length' => 1,
+     *                                                'default' => 'M',
+     *                                            ),
+     *                                        )
+     *                                    )
+     *                                )
+     *
+     * @param boolean $check     indicates whether the function should just check if the DBMS driver
+     *                             can perform the requested table alterations if the value is true or
+     *                             actually perform them otherwise.
+     * @access public
+     *
+      * @return mixed MDB2_OK on success, a MDB2 error on failure
+     */
+    function alterTable($name, $changes, $check)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ listDatabases()
+
+    /**
+     * list all databases
+     *
+     * @return mixed array of database names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listDatabases()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implementedd', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ listUsers()
+
+    /**
+     * list all users
+     *
+     * @return mixed array of user names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listUsers()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ listViews()
+
+    /**
+     * list all views in the current database
+     *
+     * @param string database, the current is default
+     *               NB: not all the drivers can get the view names from
+     *               a database other than the current one
+     * @return mixed array of view names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listViews($database = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ listTableViews()
+
+    /**
+     * list the views in the database that reference a given table
+     *
+     * @param string table for which all referenced views should be found
+     * @return mixed array of view names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableViews($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ listTableTriggers()
+
+    /**
+     * list all triggers in the database that reference a given table
+     *
+     * @param string table for which all referenced triggers should be found
+     * @return mixed array of trigger names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableTriggers($table = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ listFunctions()
+
+    /**
+     * list all functions in the current database
+     *
+     * @return mixed array of function names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listFunctions()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ listTables()
+
+    /**
+     * list all tables in the current database
+     *
+     * @param string database, the current is default.
+     *               NB: not all the drivers can get the table names from
+     *               a database other than the current one
+     * @return mixed array of table names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTables($database = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ listTableFields()
+
+    /**
+     * list all fields in a table in the current database
+     *
+     * @param string $table name of table that should be used in method
+     * @return mixed array of field names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableFields($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ createIndex()
+
+    /**
+     * Get the stucture of a field into an array
+     *
+     * @param string    $table         name of the table on which the index is to be created
+     * @param string    $name         name of the index to be created
+     * @param array     $definition        associative array that defines properties of the index to be created.
+     *                                 Currently, only one property named FIELDS is supported. This property
+     *                                 is also an associative with the names of the index fields as array
+     *                                 indexes. Each entry of this array is set to another type of associative
+     *                                 array that specifies properties of the index that are specific to
+     *                                 each field.
+     *
+     *                                Currently, only the sorting property is supported. It should be used
+     *                                 to define the sorting direction of the index. It may be set to either
+     *                                 ascending or descending.
+     *
+     *                                Not all DBMS support index sorting direction configuration. The DBMS
+     *                                 drivers of those that do not support it ignore this property. Use the
+     *                                 function supports() to determine whether the DBMS driver can manage indexes.
+     *
+     *                                 Example
+     *                                    array(
+     *                                        'fields' => array(
+     *                                            'user_name' => array(
+     *                                                'sorting' => 'ascending'
+     *                                            ),
+     *                                            'last_login' => array()
+     *                                        )
+     *                                    )
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createIndex($table, $name, $definition)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $table = $db->quoteIdentifier($table, true);
+        $name = $db->quoteIdentifier($db->getIndexName($name), true);
+        $query = "CREATE INDEX $name ON $table";
+        $fields = array();
+        foreach (array_keys($definition['fields']) as $field) {
+            $fields[] = $db->quoteIdentifier($field, true);
+        }
+        $query .= ' ('. implode(', ', $fields) . ')';
+        return $db->exec($query);
+    }
+
+    // }}}
+    // {{{ dropIndex()
+
+    /**
+     * drop existing index
+     *
+     * @param string    $table         name of table that should be used in method
+     * @param string    $name         name of the index to be dropped
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropIndex($table, $name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $name = $db->quoteIdentifier($db->getIndexName($name), true);
+        return $db->exec("DROP INDEX $name");
+    }
+
+    // }}}
+    // {{{ listTableIndexes()
+
+    /**
+     * list all indexes in a table
+     *
+     * @param string $table name of table that should be used in method
+     * @return mixed array of index names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableIndexes($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ createConstraint()
+
+    /**
+     * create a constraint on a table
+     *
+     * @param string    $table         name of the table on which the constraint is to be created
+     * @param string    $name         name of the constraint to be created
+     * @param array     $definition        associative array that defines properties of the constraint to be created.
+     *                                 Currently, only one property named FIELDS is supported. This property
+     *                                 is also an associative with the names of the constraint fields as array
+     *                                 constraints. Each entry of this array is set to another type of associative
+     *                                 array that specifies properties of the constraint that are specific to
+     *                                 each field.
+     *
+     *                                 Example
+     *                                    array(
+     *                                        'fields' => array(
+     *                                            'user_name' => array(),
+     *                                            'last_login' => array()
+     *                                        )
+     *                                    )
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createConstraint($table, $name, $definition)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+        $table = $db->quoteIdentifier($table, true);
+        $name = $db->quoteIdentifier($db->getIndexName($name), true);
+        $query = "ALTER TABLE $table ADD CONSTRAINT $name";
+        if (!empty($definition['primary'])) {
+            $query.= ' PRIMARY KEY';
+        } elseif (!empty($definition['unique'])) {
+            $query.= ' UNIQUE';
+        }
+        $fields = array();
+        foreach (array_keys($definition['fields']) as $field) {
+            $fields[] = $db->quoteIdentifier($field, true);
+        }
+        $query .= ' ('. implode(', ', $fields) . ')';
+        return $db->exec($query);
+    }
+
+    // }}}
+    // {{{ dropConstraint()
+
+    /**
+     * drop existing constraint
+     *
+     * @param string    $table        name of table that should be used in method
+     * @param string    $name         name of the constraint to be dropped
+     * @param string    $primary      hint if the constraint is primary
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropConstraint($table, $name, $primary = false)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $table = $db->quoteIdentifier($table, true);
+        $name = $db->quoteIdentifier($db->getIndexName($name), true);
+        return $db->exec("ALTER TABLE $table DROP CONSTRAINT $name");
+    }
+
+    // }}}
+    // {{{ listTableConstraints()
+
+    /**
+     * list all constraints in a table
+     *
+     * @param string $table name of table that should be used in method
+     * @return mixed array of constraint names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableConstraints($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ createSequence()
+
+    /**
+     * create sequence
+     *
+     * @param string    $seq_name     name of the sequence to be created
+     * @param string    $start         start value of the sequence; default is 1
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createSequence($seq_name, $start = 1)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ dropSequence()
+
+    /**
+     * drop existing sequence
+     *
+     * @param string    $seq_name     name of the sequence to be dropped
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropSequence($name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ listSequences()
+
+    /**
+     * list all sequences in the current database
+     *
+     * @param string database, the current is default
+     *               NB: not all the drivers can get the sequence names from
+     *               a database other than the current one
+     * @return mixed array of sequence names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listSequences($database = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Manager/mysql.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Manager/mysql.php
new file mode 100644 (file)
index 0000000..1e0aa05
--- /dev/null
@@ -0,0 +1,1001 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: mysql.php,v 1.94 2007/03/04 22:50:16 quipo Exp $
+//
+
+require_once 'MDB2/Driver/Manager/Common.php';
+
+/**
+ * MDB2 MySQL driver for the management modules
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
+{
+
+    // }}}
+    // {{{ createDatabase()
+
+    /**
+     * create a new database
+     *
+     * @param string $name name of the database that should be created
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createDatabase($name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $name = $db->quoteIdentifier($name, true);
+        $query = "CREATE DATABASE $name";
+        $result = $db->exec($query);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ dropDatabase()
+
+    /**
+     * drop an existing database
+     *
+     * @param string $name name of the database that should be dropped
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropDatabase($name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $name = $db->quoteIdentifier($name, true);
+        $query = "DROP DATABASE $name";
+        $result = $db->exec($query);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ createTable()
+
+    /**
+     * create a new table
+     *
+     * @param string $name   Name of the database that should be created
+     * @param array $fields  Associative array that contains the definition of each field of the new table
+     *                       The indexes of the array entries are the names of the fields of the table an
+     *                       the array entry values are associative arrays like those that are meant to be
+     *                       passed with the field definitions to get[Type]Declaration() functions.
+     *                          array(
+     *                              'id' => array(
+     *                                  'type' => 'integer',
+     *                                  'unsigned' => 1
+     *                                  'notnull' => 1
+     *                                  'default' => 0
+     *                              ),
+     *                              'name' => array(
+     *                                  'type' => 'text',
+     *                                  'length' => 12
+     *                              ),
+     *                              'password' => array(
+     *                                  'type' => 'text',
+     *                                  'length' => 12
+     *                              )
+     *                          );
+     * @param array $options  An associative array of table options:
+     *                          array(
+     *                              'comment' => 'Foo',
+     *                              'charset' => 'utf8',
+     *                              'collate' => 'utf8_unicode_ci',
+     *                              'type'    => 'innodb',
+     *                          );
+     *
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createTable($name, $fields, $options = array())
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = $this->_getCreateTableQuery($name, $fields, $options);
+        if (PEAR::isError($query)) {
+            return $query;
+        }
+
+        $options_strings = array();
+
+        if (!empty($options['comment'])) {
+            $options_strings['comment'] = 'COMMENT = '.$db->quote($options['comment'], 'text');
+        }
+
+        if (!empty($options['charset'])) {
+            $options_strings['charset'] = 'DEFAULT CHARACTER SET '.$options['charset'];
+            if (!empty($options['collate'])) {
+                $options_strings['charset'].= ' COLLATE '.$options['collate'];
+            }
+        }
+
+        $type = false;
+        if (!empty($options['type'])) {
+            $type = $options['type'];
+        } elseif ($db->options['default_table_type']) {
+            $type = $db->options['default_table_type'];
+        }
+        if ($type) {
+            $options_strings[] = "ENGINE = $type";
+        }
+
+        if (!empty($options_strings)) {
+            $query .= ' '.implode(' ', $options_strings);
+        }
+        return $db->exec($query);
+    }
+
+    // }}}
+    // {{{ alterTable()
+
+    /**
+     * alter an existing table
+     *
+     * @param string $name         name of the table that is intended to be changed.
+     * @param array $changes     associative array that contains the details of each type
+     *                             of change that is intended to be performed. The types of
+     *                             changes that are currently supported are defined as follows:
+     *
+     *                             name
+     *
+     *                                New name for the table.
+     *
+     *                            add
+     *
+     *                                Associative array with the names of fields to be added as
+     *                                 indexes of the array. The value of each entry of the array
+     *                                 should be set to another associative array with the properties
+     *                                 of the fields to be added. The properties of the fields should
+     *                                 be the same as defined by the MDB2 parser.
+     *
+     *
+     *                            remove
+     *
+     *                                Associative array with the names of fields to be removed as indexes
+     *                                 of the array. Currently the values assigned to each entry are ignored.
+     *                                 An empty array should be used for future compatibility.
+     *
+     *                            rename
+     *
+     *                                Associative array with the names of fields to be renamed as indexes
+     *                                 of the array. The value of each entry of the array should be set to
+     *                                 another associative array with the entry named name with the new
+     *                                 field name and the entry named Declaration that is expected to contain
+     *                                 the portion of the field declaration already in DBMS specific SQL code
+     *                                 as it is used in the CREATE TABLE statement.
+     *
+     *                            change
+     *
+     *                                Associative array with the names of the fields to be changed as indexes
+     *                                 of the array. Keep in mind that if it is intended to change either the
+     *                                 name of a field and any other properties, the change array entries
+     *                                 should have the new names of the fields as array indexes.
+     *
+     *                                The value of each entry of the array should be set to another associative
+     *                                 array with the properties of the fields to that are meant to be changed as
+     *                                 array entries. These entries should be assigned to the new values of the
+     *                                 respective properties. The properties of the fields should be the same
+     *                                 as defined by the MDB2 parser.
+     *
+     *                            Example
+     *                                array(
+     *                                    'name' => 'userlist',
+     *                                    'add' => array(
+     *                                        'quota' => array(
+     *                                            'type' => 'integer',
+     *                                            'unsigned' => 1
+     *                                        )
+     *                                    ),
+     *                                    'remove' => array(
+     *                                        'file_limit' => array(),
+     *                                        'time_limit' => array()
+     *                                    ),
+     *                                    'change' => array(
+     *                                        'name' => array(
+     *                                            'length' => '20',
+     *                                            'definition' => array(
+     *                                                'type' => 'text',
+     *                                                'length' => 20,
+     *                                            ),
+     *                                        )
+     *                                    ),
+     *                                    'rename' => array(
+     *                                        'sex' => array(
+     *                                            'name' => 'gender',
+     *                                            'definition' => array(
+     *                                                'type' => 'text',
+     *                                                'length' => 1,
+     *                                                'default' => 'M',
+     *                                            ),
+     *                                        )
+     *                                    )
+     *                                )
+     *
+     * @param boolean $check     indicates whether the function should just check if the DBMS driver
+     *                             can perform the requested table alterations if the value is true or
+     *                             actually perform them otherwise.
+     * @access public
+     *
+      * @return mixed MDB2_OK on success, a MDB2 error on failure
+     */
+    function alterTable($name, $changes, $check)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        foreach ($changes as $change_name => $change) {
+            switch ($change_name) {
+            case 'add':
+            case 'remove':
+            case 'change':
+            case 'rename':
+            case 'name':
+                break;
+            default:
+                return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
+                    'change type "'.$change_name.'" not yet supported', __FUNCTION__);
+            }
+        }
+
+        if ($check) {
+            return MDB2_OK;
+        }
+
+        $query = '';
+        if (!empty($changes['name'])) {
+            $change_name = $db->quoteIdentifier($changes['name'], true);
+            $query .= 'RENAME TO ' . $change_name;
+        }
+
+        if (!empty($changes['add']) && is_array($changes['add'])) {
+            foreach ($changes['add'] as $field_name => $field) {
+                if ($query) {
+                    $query.= ', ';
+                }
+                $query.= 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field);
+            }
+        }
+
+        if (!empty($changes['remove']) && is_array($changes['remove'])) {
+            foreach ($changes['remove'] as $field_name => $field) {
+                if ($query) {
+                    $query.= ', ';
+                }
+                $field_name = $db->quoteIdentifier($field_name, true);
+                $query.= 'DROP ' . $field_name;
+            }
+        }
+
+        $rename = array();
+        if (!empty($changes['rename']) && is_array($changes['rename'])) {
+            foreach ($changes['rename'] as $field_name => $field) {
+                $rename[$field['name']] = $field_name;
+            }
+        }
+
+        if (!empty($changes['change']) && is_array($changes['change'])) {
+            foreach ($changes['change'] as $field_name => $field) {
+                if ($query) {
+                    $query.= ', ';
+                }
+                if (isset($rename[$field_name])) {
+                    $old_field_name = $rename[$field_name];
+                    unset($rename[$field_name]);
+                } else {
+                    $old_field_name = $field_name;
+                }
+                $old_field_name = $db->quoteIdentifier($old_field_name, true);
+                $query.= "CHANGE $old_field_name " . $db->getDeclaration($field['definition']['type'], $field_name, $field['definition']);
+            }
+        }
+
+        if (!empty($rename) && is_array($rename)) {
+            foreach ($rename as $rename_name => $renamed_field) {
+                if ($query) {
+                    $query.= ', ';
+                }
+                $field = $changes['rename'][$renamed_field];
+                $renamed_field = $db->quoteIdentifier($renamed_field, true);
+                $query.= 'CHANGE ' . $renamed_field . ' ' . $db->getDeclaration($field['definition']['type'], $field['name'], $field['definition']);
+            }
+        }
+
+        if (!$query) {
+            return MDB2_OK;
+        }
+
+        $name = $db->quoteIdentifier($name, true);
+        return $db->exec("ALTER TABLE $name $query");
+    }
+
+    // }}}
+    // {{{ listDatabases()
+
+    /**
+     * list all databases
+     *
+     * @return mixed array of database names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listDatabases()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $result = $db->queryCol('SHOW DATABASES');
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ listUsers()
+
+    /**
+     * list all users
+     *
+     * @return mixed array of user names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listUsers()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->queryCol('SELECT DISTINCT USER FROM mysql.USER');
+    }
+
+    // }}}
+    // {{{ listFunctions()
+
+    /**
+     * list all functions in the current database
+     *
+     * @return mixed array of function names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listFunctions()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = "SELECT name FROM mysql.proc";
+        /*
+        SELECT ROUTINE_NAME
+          FROM INFORMATION_SCHEMA.ROUTINES
+         WHERE ROUTINE_TYPE = 'FUNCTION'
+        */
+        $result = $db->queryCol($query);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ listTableTriggers()
+
+    /**
+     * list all triggers in the database that reference a given table
+     *
+     * @param string table for which all referenced triggers should be found
+     * @return mixed array of trigger names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableTriggers($table = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = 'SHOW TRIGGERS';
+        if (!is_null($table)) {
+            $table = $db->quote($table, 'text');
+            $query .= " LIKE $table";
+        }
+        $result = $db->queryCol($query);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ listTables()
+
+    /**
+     * list all tables in the current database
+     *
+     * @param string database, the current is default
+     * @return mixed array of table names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTables($database = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = "SHOW /*!50002 FULL*/ TABLES";
+        if (!is_null($database)) {
+            $query .= " FROM $database";
+        }
+        $query.= "/*!50002  WHERE Table_type = 'BASE TABLE'*/";
+
+        $table_names = $db->queryAll($query, null, MDB2_FETCHMODE_ORDERED);
+        if (PEAR::isError($table_names)) {
+            return $table_names;
+        }
+
+        $result = array();
+        foreach ($table_names as $table) {
+            if (!$this->_fixSequenceName($table[0], true)) {
+                $result[] = $table[0];
+            }
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ listViews()
+
+    /**
+     * list all views in the current database
+     *
+     * @param string database, the current is default
+     * @return mixed array of view names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listViews($database = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = 'SHOW FULL TABLES';
+        if (!is_null($database)) {
+            $query.= " FROM $database";
+        }
+        $query.= " WHERE Table_type = 'VIEW'";
+
+        $result = $db->queryCol($query);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ listTableFields()
+
+    /**
+     * list all fields in a table in the current database
+     *
+     * @param string $table name of table that should be used in method
+     * @return mixed array of field names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableFields($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $table = $db->quoteIdentifier($table, true);
+        $result = $db->queryCol("SHOW COLUMNS FROM $table");
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ createIndex()
+
+    /**
+     * Get the stucture of a field into an array
+     *
+     * @author Leoncx
+     * @param string    $table         name of the table on which the index is to be created
+     * @param string    $name         name of the index to be created
+     * @param array     $definition        associative array that defines properties of the index to be created.
+     *                                 Currently, only one property named FIELDS is supported. This property
+     *                                 is also an associative with the names of the index fields as array
+     *                                 indexes. Each entry of this array is set to another type of associative
+     *                                 array that specifies properties of the index that are specific to
+     *                                 each field.
+     *
+     *                                Currently, only the sorting property is supported. It should be used
+     *                                 to define the sorting direction of the index. It may be set to either
+     *                                 ascending or descending.
+     *
+     *                                Not all DBMS support index sorting direction configuration. The DBMS
+     *                                 drivers of those that do not support it ignore this property. Use the
+     *                                 function supports() to determine whether the DBMS driver can manage indexes.
+     *
+     *                                 Example
+     *                                    array(
+     *                                        'fields' => array(
+     *                                            'user_name' => array(
+     *                                                'sorting' => 'ascending'
+     *                                                'length' => 10
+     *                                            ),
+     *                                            'last_login' => array()
+     *                                        )
+     *                                    )
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createIndex($table, $name, $definition)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $table = $db->quoteIdentifier($table, true);
+        $name = $db->quoteIdentifier($db->getIndexName($name), true);
+        $query = "CREATE INDEX $name ON $table";
+        $fields = array();
+        foreach ($definition['fields'] as $field => $fieldinfo) {
+            if (!empty($fieldinfo['length'])) {
+                $fields[] = $db->quoteIdentifier($field, true) . '(' . $fieldinfo['length'] . ')';
+            } else {
+                $fields[] = $db->quoteIdentifier($field, true);
+            }
+        }
+        $query .= ' ('. implode(', ', $fields) . ')';
+        return $db->exec($query);
+    }
+
+    // }}}
+    // {{{ dropIndex()
+
+    /**
+     * drop existing index
+     *
+     * @param string    $table         name of table that should be used in method
+     * @param string    $name         name of the index to be dropped
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropIndex($table, $name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $table = $db->quoteIdentifier($table, true);
+        $name = $db->quoteIdentifier($db->getIndexName($name), true);
+        return $db->exec("DROP INDEX $name ON $table");
+    }
+
+    // }}}
+    // {{{ listTableIndexes()
+
+    /**
+     * list all indexes in a table
+     *
+     * @param string $table name of table that should be used in method
+     * @return mixed array of index names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableIndexes($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $key_name = 'Key_name';
+        $non_unique = 'Non_unique';
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            if ($db->options['field_case'] == CASE_LOWER) {
+                $key_name = strtolower($key_name);
+                $non_unique = strtolower($non_unique);
+            } else {
+                $key_name = strtoupper($key_name);
+                $non_unique = strtoupper($non_unique);
+            }
+        }
+
+        $table = $db->quoteIdentifier($table, true);
+        $query = "SHOW INDEX FROM $table";
+        $indexes = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
+        if (PEAR::isError($indexes)) {
+            return $indexes;
+        }
+
+        $result = array();
+        foreach ($indexes as $index_data) {
+            if ($index_data[$non_unique] && ($index = $this->_fixIndexName($index_data[$key_name]))) {
+                $result[$index] = true;
+            }
+        }
+
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_change_key_case($result, $db->options['field_case']);
+        }
+        return array_keys($result);
+    }
+
+    // }}}
+    // {{{ createConstraint()
+
+    /**
+     * create a constraint on a table
+     *
+     * @param string    $table        name of the table on which the constraint is to be created
+     * @param string    $name         name of the constraint to be created
+     * @param array     $definition   associative array that defines properties of the constraint to be created.
+     *                                Currently, only one property named FIELDS is supported. This property
+     *                                is also an associative with the names of the constraint fields as array
+     *                                constraints. Each entry of this array is set to another type of associative
+     *                                array that specifies properties of the constraint that are specific to
+     *                                each field.
+     *
+     *                                Example
+     *                                   array(
+     *                                       'fields' => array(
+     *                                           'user_name' => array(),
+     *                                           'last_login' => array()
+     *                                       )
+     *                                   )
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createConstraint($table, $name, $definition)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $type = '';
+        $name = $db->quoteIdentifier($db->getIndexName($name), true);
+        if (!empty($definition['primary'])) {
+            $type = 'PRIMARY';
+            $name = 'KEY';
+        } elseif (!empty($definition['unique'])) {
+            $type = 'UNIQUE';
+        }
+        if (empty($type)) {
+            return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                'invalid definition, could not create constraint', __FUNCTION__);
+        }
+
+        $table = $db->quoteIdentifier($table, true);
+        $query = "ALTER TABLE $table ADD $type $name";
+        $fields = array();
+        foreach (array_keys($definition['fields']) as $field) {
+            $fields[] = $db->quoteIdentifier($field, true);
+        }
+        $query .= ' ('. implode(', ', $fields) . ')';
+        return $db->exec($query);
+    }
+
+    // }}}
+    // {{{ dropConstraint()
+
+    /**
+     * drop existing constraint
+     *
+     * @param string    $table        name of table that should be used in method
+     * @param string    $name         name of the constraint to be dropped
+     * @param string    $primary      hint if the constraint is primary
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropConstraint($table, $name, $primary = false)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $table = $db->quoteIdentifier($table, true);
+        if ($primary || strtolower($name) == 'primary') {
+            $query = "ALTER TABLE $table DROP PRIMARY KEY";
+        } else {
+            $name = $db->quoteIdentifier($db->getIndexName($name), true);
+            $query = "ALTER TABLE $table DROP INDEX $name";
+        }
+        return $db->exec($query);
+    }
+
+    // }}}
+    // {{{ listTableConstraints()
+
+    /**
+     * list all constraints in a table
+     *
+     * @param string $table name of table that should be used in method
+     * @return mixed array of constraint names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableConstraints($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $key_name = 'Key_name';
+        $non_unique = 'Non_unique';
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            if ($db->options['field_case'] == CASE_LOWER) {
+                $key_name = strtolower($key_name);
+                $non_unique = strtolower($non_unique);
+            } else {
+                $key_name = strtoupper($key_name);
+                $non_unique = strtoupper($non_unique);
+            }
+        }
+
+        $table = $db->quoteIdentifier($table, true);
+        $query = "SHOW INDEX FROM $table";
+        $indexes = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
+        if (PEAR::isError($indexes)) {
+            return $indexes;
+        }
+
+        $result = array();
+        foreach ($indexes as $index_data) {
+            if (!$index_data[$non_unique]) {
+                if ($index_data[$key_name] !== 'PRIMARY') {
+                    $index = $this->_fixIndexName($index_data[$key_name]);
+                } else {
+                    $index = 'PRIMARY';
+                }
+                if (!empty($index)) {
+                    $result[$index] = true;
+                }
+            }
+        }
+
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_change_key_case($result, $db->options['field_case']);
+        }
+        return array_keys($result);
+    }
+
+    // }}}
+    // {{{ createSequence()
+
+    /**
+     * create sequence
+     *
+     * @param string    $seq_name name of the sequence to be created
+     * @param string    $start    start value of the sequence; default is 1
+     * @param array     $options  An associative array of table options:
+     *                          array(
+     *                              'comment' => 'Foo',
+     *                              'charset' => 'utf8',
+     *                              'collate' => 'utf8_unicode_ci',
+     *                              'type'    => 'innodb',
+     *                          );
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createSequence($seq_name, $start = 1, $options = array())
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
+        $seqcol_name = $db->quoteIdentifier($db->options['seqcol_name'], true);
+        
+        $options_strings = array();
+
+        if (!empty($options['comment'])) {
+            $options_strings['comment'] = 'COMMENT = '.$db->quote($options['comment'], 'text');
+        }
+
+        if (!empty($options['charset'])) {
+            $options_strings['charset'] = 'DEFAULT CHARACTER SET '.$options['charset'];
+            if (!empty($options['collate'])) {
+                $options_strings['charset'].= ' COLLATE '.$options['collate'];
+            }
+        }
+
+        $type = false;
+        if (!empty($options['type'])) {
+            $type = $options['type'];
+        } elseif ($db->options['default_table_type']) {
+            $type = $db->options['default_table_type'];
+        }
+        if ($type) {
+            $options_strings[] = "ENGINE = $type";
+        }
+
+        $query = "CREATE TABLE $sequence_name ($seqcol_name INT NOT NULL AUTO_INCREMENT, PRIMARY KEY ($seqcol_name))";
+        if (!empty($options_strings)) {
+            $query .= ' '.implode(' ', $options_strings);
+        }
+        $res = $db->exec($query);
+
+        if (PEAR::isError($res)) {
+            return $res;
+        }
+
+        if ($start == 1) {
+            return MDB2_OK;
+        }
+
+        $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (".($start-1).')';
+        $res = $db->exec($query);
+        if (!PEAR::isError($res)) {
+            return MDB2_OK;
+        }
+
+        // Handle error
+        $result = $db->exec("DROP TABLE $sequence_name");
+        if (PEAR::isError($result)) {
+            return $db->raiseError($result, null, null,
+                'could not drop inconsistent sequence table', __FUNCTION__);
+        }
+
+        return $db->raiseError($res, null, null,
+            'could not create sequence table', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ dropSequence()
+
+    /**
+     * drop existing sequence
+     *
+     * @param string    $seq_name     name of the sequence to be dropped
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropSequence($seq_name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
+        return $db->exec("DROP TABLE $sequence_name");
+    }
+
+    // }}}
+    // {{{ listSequences()
+
+    /**
+     * list all sequences in the current database
+     *
+     * @param string database, the current is default
+     * @return mixed array of sequence names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listSequences($database = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = "SHOW TABLES";
+        if (!is_null($database)) {
+            $query .= " FROM $database";
+        }
+        $table_names = $db->queryCol($query);
+        if (PEAR::isError($table_names)) {
+            return $table_names;
+        }
+
+        $result = array();
+        foreach ($table_names as $table_name) {
+            if ($sqn = $this->_fixSequenceName($table_name, true)) {
+                $result[] = $sqn;
+            }
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Manager/pgsql.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Manager/pgsql.php
new file mode 100644 (file)
index 0000000..9f2a828
--- /dev/null
@@ -0,0 +1,723 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Paul Cooper <pgc@ucecom.com>                                 |
+// +----------------------------------------------------------------------+
+//
+// $Id: pgsql.php,v 1.70 2007/04/10 20:35:49 nrf Exp $
+
+require_once 'MDB2/Driver/Manager/Common.php';
+
+/**
+ * MDB2 MySQL driver for the management modules
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Paul Cooper <pgc@ucecom.com>
+ */
+class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
+{
+    // {{{ createDatabase()
+
+    /**
+     * create a new database
+     *
+     * @param string $name name of the database that should be created
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createDatabase($name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $name = $db->quoteIdentifier($name, true);
+        return $db->standaloneQuery("CREATE DATABASE $name", null, true);
+    }
+
+    // }}}
+    // {{{ dropDatabase()
+
+    /**
+     * drop an existing database
+     *
+     * @param string $name name of the database that should be dropped
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropDatabase($name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $name = $db->quoteIdentifier($name, true);
+        return $db->standaloneQuery("DROP DATABASE $name", null, true);
+    }
+
+    // }}}
+    // {{{ alterTable()
+
+    /**
+     * alter an existing table
+     *
+     * @param string $name         name of the table that is intended to be changed.
+     * @param array $changes     associative array that contains the details of each type
+     *                             of change that is intended to be performed. The types of
+     *                             changes that are currently supported are defined as follows:
+     *
+     *                             name
+     *
+     *                                New name for the table.
+     *
+     *                            add
+     *
+     *                                Associative array with the names of fields to be added as
+     *                                 indexes of the array. The value of each entry of the array
+     *                                 should be set to another associative array with the properties
+     *                                 of the fields to be added. The properties of the fields should
+     *                                 be the same as defined by the MDB2 parser.
+     *
+     *
+     *                            remove
+     *
+     *                                Associative array with the names of fields to be removed as indexes
+     *                                 of the array. Currently the values assigned to each entry are ignored.
+     *                                 An empty array should be used for future compatibility.
+     *
+     *                            rename
+     *
+     *                                Associative array with the names of fields to be renamed as indexes
+     *                                 of the array. The value of each entry of the array should be set to
+     *                                 another associative array with the entry named name with the new
+     *                                 field name and the entry named Declaration that is expected to contain
+     *                                 the portion of the field declaration already in DBMS specific SQL code
+     *                                 as it is used in the CREATE TABLE statement.
+     *
+     *                            change
+     *
+     *                                Associative array with the names of the fields to be changed as indexes
+     *                                 of the array. Keep in mind that if it is intended to change either the
+     *                                 name of a field and any other properties, the change array entries
+     *                                 should have the new names of the fields as array indexes.
+     *
+     *                                The value of each entry of the array should be set to another associative
+     *                                 array with the properties of the fields to that are meant to be changed as
+     *                                 array entries. These entries should be assigned to the new values of the
+     *                                 respective properties. The properties of the fields should be the same
+     *                                 as defined by the MDB2 parser.
+     *
+     *                            Example
+     *                                array(
+     *                                    'name' => 'userlist',
+     *                                    'add' => array(
+     *                                        'quota' => array(
+     *                                            'type' => 'integer',
+     *                                            'unsigned' => 1
+     *                                        )
+     *                                    ),
+     *                                    'remove' => array(
+     *                                        'file_limit' => array(),
+     *                                        'time_limit' => array()
+     *                                    ),
+     *                                    'change' => array(
+     *                                        'name' => array(
+     *                                            'length' => '20',
+     *                                            'definition' => array(
+     *                                                'type' => 'text',
+     *                                                'length' => 20,
+     *                                            ),
+     *                                        )
+     *                                    ),
+     *                                    'rename' => array(
+     *                                        'sex' => array(
+     *                                            'name' => 'gender',
+     *                                            'definition' => array(
+     *                                                'type' => 'text',
+     *                                                'length' => 1,
+     *                                                'default' => 'M',
+     *                                            ),
+     *                                        )
+     *                                    )
+     *                                )
+     *
+     * @param boolean $check     indicates whether the function should just check if the DBMS driver
+     *                             can perform the requested table alterations if the value is true or
+     *                             actually perform them otherwise.
+     * @access public
+     *
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     */
+    function alterTable($name, $changes, $check)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        foreach ($changes as $change_name => $change) {
+            switch ($change_name) {
+            case 'add':
+            case 'remove':
+            case 'change':
+            case 'name':
+            case 'rename':
+                break;
+            default:
+                return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
+                    'change type "'.$change_name.'\" not yet supported', __FUNCTION__);
+            }
+        }
+
+        if ($check) {
+            return MDB2_OK;
+        }
+
+        if (!empty($changes['add']) && is_array($changes['add'])) {
+            foreach ($changes['add'] as $field_name => $field) {
+                $query = 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field);
+                $result = $db->exec("ALTER TABLE $name $query");
+                if (PEAR::isError($result)) {
+                    return $result;
+                }
+            }
+        }
+
+        if (!empty($changes['remove']) && is_array($changes['remove'])) {
+            foreach ($changes['remove'] as $field_name => $field) {
+                $field_name = $db->quoteIdentifier($field_name, true);
+                $query = 'DROP ' . $field_name;
+                $result = $db->exec("ALTER TABLE $name $query");
+                if (PEAR::isError($result)) {
+                    return $result;
+                }
+            }
+        }
+
+        if (!empty($changes['change']) && is_array($changes['change'])) {
+            foreach ($changes['change'] as $field_name => $field) {
+                $field_name = $db->quoteIdentifier($field_name, true);
+                if (!empty($field['type'])) {
+                    $server_info = $db->getServerVersion();
+                    if (PEAR::isError($server_info)) {
+                        return $server_info;
+                    }
+                    if (is_array($server_info) && $server_info['major'] < 8) {
+                        return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
+                            'changing column type for "'.$change_name.'\" requires PostgreSQL 8.0 or above', __FUNCTION__);
+                    }
+                    $db->loadModule('Datatype', null, true);
+                    $query = "ALTER $field_name TYPE ".$db->datatype->getTypeDeclaration($field['definition']);
+                    $result = $db->exec("ALTER TABLE $name $query");
+                    if (PEAR::isError($result)) {
+                        return $result;
+                    }
+                }
+                if (array_key_exists('default', $field)) {
+                    $query = "ALTER $field_name SET DEFAULT ".$db->quote($field['definition']['default'], $field['definition']['type']);
+                    $result = $db->exec("ALTER TABLE $name $query");
+                    if (PEAR::isError($result)) {
+                        return $result;
+                    }
+                }
+                if (!empty($field['notnull'])) {
+                    $query = "ALTER $field_name ".($field['definition']['notnull'] ? "SET" : "DROP").' NOT NULL';
+                    $result = $db->exec("ALTER TABLE $name $query");
+                    if (PEAR::isError($result)) {
+                        return $result;
+                    }
+                }
+            }
+        }
+
+        if (!empty($changes['rename']) && is_array($changes['rename'])) {
+            foreach ($changes['rename'] as $field_name => $field) {
+                $field_name = $db->quoteIdentifier($field_name, true);
+                $result = $db->exec("ALTER TABLE $name RENAME COLUMN $field_name TO ".$db->quoteIdentifier($field['name'], true));
+                if (PEAR::isError($result)) {
+                    return $result;
+                }
+            }
+        }
+
+        $name = $db->quoteIdentifier($name, true);
+        if (!empty($changes['name'])) {
+            $change_name = $db->quoteIdentifier($changes['name'], true);
+            $result = $db->exec("ALTER TABLE $name RENAME TO ".$change_name);
+            if (PEAR::isError($result)) {
+                return $result;
+            }
+        }
+
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ listDatabases()
+
+    /**
+     * list all databases
+     *
+     * @return mixed array of database names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listDatabases()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = 'SELECT datname FROM pg_database';
+        $result2 = $db->standaloneQuery($query, array('text'), false);
+        if (!MDB2::isResultCommon($result2)) {
+            return $result2;
+        }
+
+        $result = $result2->fetchCol();
+        $result2->free();
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ listUsers()
+
+    /**
+     * list all users
+     *
+     * @return mixed array of user names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listUsers()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = 'SELECT usename FROM pg_user';
+        $result2 = $db->standaloneQuery($query, array('text'), false);
+        if (!MDB2::isResultCommon($result2)) {
+            return $result2;
+        }
+
+        $result = $result2->fetchCol();
+        $result2->free();
+        return $result;
+    }
+
+    // }}}
+    // {{{ listViews()
+
+    /**
+     * list all views in the current database
+     *
+     * @return mixed array of view names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listViews()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = "SELECT viewname
+                    FROM pg_views
+                   WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
+                     AND viewname !~ '^pg_'";
+        $result = $db->queryCol($query);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ listTableViews()
+
+    /**
+     * list the views in the database that reference a given table
+     *
+     * @param string table for which all referenced views should be found
+     * @return mixed array of view names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableViews($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = 'SELECT viewname FROM pg_views NATURAL JOIN pg_tables';
+        $query.= ' WHERE tablename ='.$db->quote($table, 'text');
+        $result = $db->queryCol($query);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ listFunctions()
+
+    /**
+     * list all functions in the current database
+     *
+     * @return mixed array of function names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listFunctions()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = "
+            SELECT
+                proname
+            FROM
+                pg_proc pr,
+                pg_type tp
+            WHERE
+                tp.oid = pr.prorettype
+                AND pr.proisagg = FALSE
+                AND tp.typname <> 'trigger'
+                AND pr.pronamespace IN
+                    (SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')";
+        $result = $db->queryCol($query);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ listTableTriggers()
+
+    /**
+     * list all triggers in the database that reference a given table
+     *
+     * @param string table for which all referenced triggers should be found
+     * @return mixed array of trigger names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableTriggers($table = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = 'SELECT trg.tgname AS trigger_name
+                    FROM pg_trigger trg,
+                         pg_class tbl
+                   WHERE trg.tgrelid = tbl.oid';
+        if (!is_null($table)) {
+            $table = $db->quote(strtoupper($table), 'text');
+            $query .= " AND tbl.relname = $table";
+        }
+        $result = $db->queryCol($query);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ listTables()
+
+    /**
+     * list all tables in the current database
+     *
+     * @return mixed array of table names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTables()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        // gratuitously stolen from PEAR DB _getSpecialQuery in pgsql.php
+        $query = 'SELECT c.relname AS "Name"'
+            . ' FROM pg_class c, pg_user u'
+            . ' WHERE c.relowner = u.usesysid'
+            . " AND c.relkind = 'r'"
+            . ' AND NOT EXISTS'
+            . ' (SELECT 1 FROM pg_views'
+            . '  WHERE viewname = c.relname)'
+            . " AND c.relname !~ '^(pg_|sql_)'"
+            . ' UNION'
+            . ' SELECT c.relname AS "Name"'
+            . ' FROM pg_class c'
+            . " WHERE c.relkind = 'r'"
+            . ' AND NOT EXISTS'
+            . ' (SELECT 1 FROM pg_views'
+            . '  WHERE viewname = c.relname)'
+            . ' AND NOT EXISTS'
+            . ' (SELECT 1 FROM pg_user'
+            . '  WHERE usesysid = c.relowner)'
+            . " AND c.relname !~ '^pg_'";
+        $result = $db->queryCol($query);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ listTableFields()
+
+    /**
+     * list all fields in a table in the current database
+     *
+     * @param string $table name of table that should be used in method
+     * @return mixed array of field names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableFields($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $table = $db->quoteIdentifier($table, true);
+        $db->setLimit(1);
+        $result2 = $db->query("SELECT * FROM $table");
+        if (PEAR::isError($result2)) {
+            return $result2;
+        }
+        $result = $result2->getColumnNames();
+        $result2->free();
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        return array_flip($result);
+    }
+
+    // }}}
+    // {{{ listTableIndexes()
+
+    /**
+     * list all indexes in a table
+     *
+     * @param string $table name of table that should be used in method
+     * @return mixed array of index names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableIndexes($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $table = $db->quote($table, 'text');
+        $subquery = "SELECT indexrelid FROM pg_index, pg_class";
+        $subquery.= " WHERE pg_class.relname=$table AND pg_class.oid=pg_index.indrelid AND indisunique != 't' AND indisprimary != 't'";
+        $query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)";
+        $indexes = $db->queryCol($query, 'text');
+        if (PEAR::isError($indexes)) {
+            return $indexes;
+        }
+
+        $result = array();
+        foreach ($indexes as $index) {
+            $index = $this->_fixIndexName($index);
+            if (!empty($index)) {
+                $result[$index] = true;
+            }
+        }
+
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_change_key_case($result, $db->options['field_case']);
+        }
+        return array_keys($result);
+    }
+
+    // }}}
+    // {{{ listTableConstraints()
+
+    /**
+     * list all constraints in a table
+     *
+     * @param string $table name of table that should be used in method
+     * @return mixed array of constraint names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableConstraints($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $table = $db->quote($table, 'text');
+        $subquery = "SELECT indexrelid FROM pg_index, pg_class";
+        $subquery.= " WHERE pg_class.relname=$table AND pg_class.oid=pg_index.indrelid AND (indisunique = 't' OR indisprimary = 't')";
+        $query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)";
+        $constraints = $db->queryCol($query);
+        if (PEAR::isError($constraints)) {
+            return $constraints;
+        }
+
+        $result = array();
+        foreach ($constraints as $constraint) {
+            $constraint = $this->_fixIndexName($constraint);
+            if (!empty($constraint)) {
+                $result[$constraint] = true;
+            }
+        }
+
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE
+            && $db->options['field_case'] == CASE_LOWER
+        ) {
+            $result = array_change_key_case($result, $db->options['field_case']);
+        }
+        return array_keys($result);
+    }
+
+    // }}}
+    // {{{ createSequence()
+
+    /**
+     * create sequence
+     *
+     * @param string $seq_name name of the sequence to be created
+     * @param string $start start value of the sequence; default is 1
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createSequence($seq_name, $start = 1)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
+        return $db->exec("CREATE SEQUENCE $sequence_name INCREMENT 1".
+            ($start < 1 ? " MINVALUE $start" : '')." START $start");
+    }
+
+    // }}}
+    // {{{ dropSequence()
+
+    /**
+     * drop existing sequence
+     *
+     * @param string $seq_name name of the sequence to be dropped
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropSequence($seq_name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
+        return $db->exec("DROP SEQUENCE $sequence_name");
+    }
+
+    // }}}
+    // {{{ listSequences()
+
+    /**
+     * list all sequences in the current database
+     *
+     * @return mixed array of sequence names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listSequences()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = "SELECT relname FROM pg_class WHERE relkind = 'S' AND relnamespace IN";
+        $query.= "(SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')";
+        $table_names = $db->queryCol($query);
+        if (PEAR::isError($table_names)) {
+            return $table_names;
+        }
+        $result = array();
+        foreach ($table_names as $table_name) {
+            $result[] = $this->_fixSequenceName($table_name);
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+}
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Manager/sqlite.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Manager/sqlite.php
new file mode 100644 (file)
index 0000000..493b596
--- /dev/null
@@ -0,0 +1,952 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Authors: Lukas Smith <smith@pooteeweet.org>                          |
+// |          Lorenzo Alberton <l.alberton@quipo.it>                      |
+// +----------------------------------------------------------------------+
+//
+// $Id: sqlite.php,v 1.62 2007/03/05 01:31:27 quipo Exp $
+//
+
+require_once 'MDB2/Driver/Manager/Common.php';
+
+/**
+ * MDB2 SQLite driver for the management modules
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ * @author  Lorenzo Alberton <l.alberton@quipo.it>
+ */
+class MDB2_Driver_Manager_sqlite extends MDB2_Driver_Manager_Common
+{
+    // {{{ createDatabase()
+
+    /**
+     * create a new database
+     *
+     * @param string $name name of the database that should be created
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createDatabase($name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $database_file = $db->_getDatabaseFile($name);
+        if (file_exists($database_file)) {
+            return $db->raiseError(MDB2_ERROR_ALREADY_EXISTS, null, null,
+                'database already exists', __FUNCTION__);
+        }
+        $php_errormsg = '';
+        $handle = @sqlite_open($database_file, $db->dsn['mode'], $php_errormsg);
+        if (!$handle) {
+            return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
+                (isset($php_errormsg) ? $php_errormsg : 'could not create the database file'), __FUNCTION__);
+        }
+        @sqlite_close($handle);
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ dropDatabase()
+
+    /**
+     * drop an existing database
+     *
+     * @param string $name name of the database that should be dropped
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropDatabase($name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $database_file = $db->_getDatabaseFile($name);
+        if (!@file_exists($database_file)) {
+            return $db->raiseError(MDB2_ERROR_CANNOT_DROP, null, null,
+                'database does not exist', __FUNCTION__);
+        }
+        $result = @unlink($database_file);
+        if (!$result) {
+            return $db->raiseError(MDB2_ERROR_CANNOT_DROP, null, null,
+                (isset($php_errormsg) ? $php_errormsg : 'could not remove the database file'), __FUNCTION__);
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ alterTable()
+
+    /**
+     * alter an existing table
+     *
+     * @param string $name         name of the table that is intended to be changed.
+     * @param array $changes     associative array that contains the details of each type
+     *                             of change that is intended to be performed. The types of
+     *                             changes that are currently supported are defined as follows:
+     *
+     *                             name
+     *
+     *                                New name for the table.
+     *
+     *                            add
+     *
+     *                                Associative array with the names of fields to be added as
+     *                                 indexes of the array. The value of each entry of the array
+     *                                 should be set to another associative array with the properties
+     *                                 of the fields to be added. The properties of the fields should
+     *                                 be the same as defined by the MDB2 parser.
+     *
+     *
+     *                            remove
+     *
+     *                                Associative array with the names of fields to be removed as indexes
+     *                                 of the array. Currently the values assigned to each entry are ignored.
+     *                                 An empty array should be used for future compatibility.
+     *
+     *                            rename
+     *
+     *                                Associative array with the names of fields to be renamed as indexes
+     *                                 of the array. The value of each entry of the array should be set to
+     *                                 another associative array with the entry named name with the new
+     *                                 field name and the entry named Declaration that is expected to contain
+     *                                 the portion of the field declaration already in DBMS specific SQL code
+     *                                 as it is used in the CREATE TABLE statement.
+     *
+     *                            change
+     *
+     *                                Associative array with the names of the fields to be changed as indexes
+     *                                 of the array. Keep in mind that if it is intended to change either the
+     *                                 name of a field and any other properties, the change array entries
+     *                                 should have the new names of the fields as array indexes.
+     *
+     *                                The value of each entry of the array should be set to another associative
+     *                                 array with the properties of the fields to that are meant to be changed as
+     *                                 array entries. These entries should be assigned to the new values of the
+     *                                 respective properties. The properties of the fields should be the same
+     *                                 as defined by the MDB2 parser.
+     *
+     *                            Example
+     *                                array(
+     *                                    'name' => 'userlist',
+     *                                    'add' => array(
+     *                                        'quota' => array(
+     *                                            'type' => 'integer',
+     *                                            'unsigned' => 1
+     *                                        )
+     *                                    ),
+     *                                    'remove' => array(
+     *                                        'file_limit' => array(),
+     *                                        'time_limit' => array()
+     *                                    ),
+     *                                    'change' => array(
+     *                                        'name' => array(
+     *                                            'length' => '20',
+     *                                            'definition' => array(
+     *                                                'type' => 'text',
+     *                                                'length' => 20,
+     *                                            ),
+     *                                        )
+     *                                    ),
+     *                                    'rename' => array(
+     *                                        'sex' => array(
+     *                                            'name' => 'gender',
+     *                                            'definition' => array(
+     *                                                'type' => 'text',
+     *                                                'length' => 1,
+     *                                                'default' => 'M',
+     *                                            ),
+     *                                        )
+     *                                    )
+     *                                )
+     *
+     * @param boolean $check     indicates whether the function should just check if the DBMS driver
+     *                             can perform the requested table alterations if the value is true or
+     *                             actually perform them otherwise.
+     * @access public
+     *
+      * @return mixed MDB2_OK on success, a MDB2 error on failure
+     */
+    function alterTable($name, $changes, $check, $options = array())
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        foreach ($changes as $change_name => $change) {
+            switch ($change_name) {
+            case 'add':
+            case 'remove':
+            case 'change':
+            case 'name':
+            case 'rename':
+                break;
+            default:
+                return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
+                    'change type "'.$change_name.'" not yet supported', __FUNCTION__);
+            }
+        }
+
+        if ($check) {
+            return MDB2_OK;
+        }
+
+        $db->loadModule('Reverse', null, true);
+
+        // actually sqlite 2.x supports no ALTER TABLE at all .. so we emulate it
+        $fields = $db->manager->listTableFields($name);
+        if (PEAR::isError($fields)) {
+            return $fields;
+        }
+
+        $fields = array_flip($fields);
+        foreach ($fields as $field => $value) {
+            $definition = $db->reverse->getTableFieldDefinition($name, $field);
+            if (PEAR::isError($definition)) {
+                return $definition;
+            }
+            $fields[$field] = $definition[0];
+        }
+
+        $indexes = $db->manager->listTableIndexes($name);
+        if (PEAR::isError($indexes)) {
+            return $indexes;
+        }
+
+        $indexes = array_flip($indexes);
+        foreach ($indexes as $index => $value) {
+            $definition = $db->reverse->getTableIndexDefinition($name, $index);
+            if (PEAR::isError($definition)) {
+                return $definition;
+            }
+            $indexes[$index] = $definition;
+        }
+
+        $constraints = $db->manager->listTableConstraints($name);
+        if (PEAR::isError($constraints)) {
+            return $constraints;
+        }
+
+        $constraints = array_flip($constraints);
+        foreach ($constraints as $constraint => $value) {
+            if (!empty($definition['primary'])) {
+                if (!array_key_exists('primary', $options)) {
+                    $options['primary'] = $definition['fields'];
+                }
+            } else {
+                $definition = $db->reverse->getTableConstraintDefinition($name, $constraint);
+                if (PEAR::isError($definition)) {
+                    return $definition;
+                }
+                $constraints[$constraint] = $definition;
+            }
+        }
+
+        $name_new = $name;
+        $create_order = $select_fields = array_keys($fields);
+        foreach ($changes as $change_name => $change) {
+            switch ($change_name) {
+            case 'add':
+                foreach ($change as $field_name => $field) {
+                    $fields[$field_name] = $field;
+                    $create_order[] = $field_name;
+                }
+                break;
+            case 'remove':
+                foreach ($change as $field_name => $field) {
+                    unset($fields[$field_name]);
+                    $select_fields = array_diff($select_fields, array($field_name));
+                    $create_order = array_diff($create_order, array($field_name));
+                }
+                break;
+            case 'change':
+                foreach ($change as $field_name => $field) {
+                    $fields[$field_name] = $field['definition'];
+                }
+                break;
+            case 'name':
+                $name_new = $change;
+                break;
+            case 'rename':
+                foreach ($change as $field_name => $field) {
+                    unset($fields[$field_name]);
+                    $fields[$field['name']] = $field['definition'];
+                    $create_order[array_search($field_name, $create_order)] = $field['name'];
+                }
+                break;
+            default:
+                return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
+                    'change type "'.$change_name.'" not yet supported', __FUNCTION__);
+            }
+        }
+
+        $data = null;
+        if (!empty($select_fields)) {
+            $query = 'SELECT '.implode(', ', $select_fields).' FROM '.$db->quoteIdentifier($name, true);
+            $data = $db->queryAll($query, null, MDB2_FETCHMODE_ORDERED);
+        }
+
+        $result = $this->dropTable($name);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+
+        $result = $this->createTable($name_new, $fields, $options);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+
+        foreach ($indexes as $index => $definition) {
+            $this->createIndex($name_new, $index, $definition);
+        }
+
+        foreach ($constraints as $constraint => $definition) {
+            $this->createConstraint($name_new, $constraint, $definition);
+        }
+
+        if (!empty($select_fields) && !empty($data)) {
+            $query = 'INSERT INTO '.$db->quoteIdentifier($name_new, true);
+            $query.= '('.implode(', ', array_slice(array_keys($fields), 0, count($select_fields))).')';
+            $query.=' VALUES (?'.str_repeat(', ?', (count($select_fields) - 1)).')';
+            $stmt =& $db->prepare($query, null, MDB2_PREPARE_MANIP);
+            if (PEAR::isError($stmt)) {
+                return $stmt;
+            }
+            foreach ($data as $row) {
+                $result = $stmt->execute($row);
+                if (PEAR::isError($result)) {
+                    return $result;
+                }
+            }
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ listDatabases()
+
+    /**
+     * list all databases
+     *
+     * @return mixed array of database names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listDatabases()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'list databases is not supported', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ listUsers()
+
+    /**
+     * list all users
+     *
+     * @return mixed array of user names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listUsers()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'list databases is not supported', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ listViews()
+
+    /**
+     * list all views in the current database
+     *
+     * @return mixed array of view names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listViews()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = "SELECT name FROM sqlite_master WHERE type='view' AND sql NOT NULL";
+        $result = $db->queryCol($query);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ listTableViews()
+
+    /**
+     * list the views in the database that reference a given table
+     *
+     * @param string table for which all referenced views should be found
+     * @return mixed array of view names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableViews($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = "SELECT name, sql FROM sqlite_master WHERE type='view' AND sql NOT NULL";
+        $views = $db->queryAll($query, array('text', 'text'), MDB2_FETCHMODE_ASSOC);
+        if (PEAR::isError($views)) {
+            return $views;
+        }
+        $result = array();
+        foreach ($views as $row) {
+            if (preg_match("/^create view .* \bfrom\b\s+\b{$table}\b /i", $row['sql'])) {
+                if (!empty($row['name'])) {
+                    $result[$row['name']] = true;
+                }
+            }
+        }
+
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_change_key_case($result, $db->options['field_case']);
+        }
+        return array_keys($result);
+    }
+
+    // }}}
+    // {{{ listTables()
+
+    /**
+     * list all tables in the current database
+     *
+     * @return mixed array of table names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTables()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = "SELECT name FROM sqlite_master WHERE type='table' AND sql NOT NULL ORDER BY name";
+        $table_names = $db->queryCol($query);
+        if (PEAR::isError($table_names)) {
+            return $table_names;
+        }
+        $result = array();
+        foreach ($table_names as $table_name) {
+            if (!$this->_fixSequenceName($table_name, true)) {
+                $result[] = $table_name;
+            }
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ listTableFields()
+
+    /**
+     * list all fields in a table in the current database
+     *
+     * @param string $table name of table that should be used in method
+     * @return mixed array of field names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableFields($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $result = $db->loadModule('Reverse', null, true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        $query = "SELECT sql FROM sqlite_master WHERE type='table' AND ";
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text');
+        } else {
+            $query.= 'name='.$db->quote($table, 'text');
+        }
+        $sql = $db->queryOne($query);
+        if (PEAR::isError($sql)) {
+            return $sql;
+        }
+        $columns = $db->reverse->_getTableColumns($sql);
+        $fields = array();
+        foreach ($columns as $column) {
+            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+                if ($db->options['field_case'] == CASE_LOWER) {
+                    $column['name'] = strtolower($column['name']);
+                } else {
+                    $column['name'] = strtoupper($column['name']);
+                }
+            } else {
+                $column = array_change_key_case($column, $db->options['field_case']);
+            }
+            $fields[] = $column['name'];
+        }
+        return $fields;
+    }
+
+    // }}}
+    // {{{ listTableTriggers()
+
+    /**
+     * list all triggers in the database that reference a given table
+     *
+     * @param string table for which all referenced triggers should be found
+     * @return mixed array of trigger names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableTriggers($table = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = "SELECT name FROM sqlite_master WHERE type='trigger' AND sql NOT NULL";
+        if (!is_null($table)) {
+            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+                $query.= ' AND LOWER(tbl_name)='.$db->quote(strtolower($table), 'text');
+            } else {
+                $query.= ' AND tbl_name='.$db->quote($table, 'text');
+            }
+        }
+        $result = $db->queryCol($query);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ createIndex()
+
+    /**
+     * Get the stucture of a field into an array
+     *
+     * @param string    $table         name of the table on which the index is to be created
+     * @param string    $name         name of the index to be created
+     * @param array     $definition        associative array that defines properties of the index to be created.
+     *                                 Currently, only one property named FIELDS is supported. This property
+     *                                 is also an associative with the names of the index fields as array
+     *                                 indexes. Each entry of this array is set to another type of associative
+     *                                 array that specifies properties of the index that are specific to
+     *                                 each field.
+     *
+     *                                Currently, only the sorting property is supported. It should be used
+     *                                 to define the sorting direction of the index. It may be set to either
+     *                                 ascending or descending.
+     *
+     *                                Not all DBMS support index sorting direction configuration. The DBMS
+     *                                 drivers of those that do not support it ignore this property. Use the
+     *                                 function support() to determine whether the DBMS driver can manage indexes.
+
+     *                                 Example
+     *                                    array(
+     *                                        'fields' => array(
+     *                                            'user_name' => array(
+     *                                                'sorting' => 'ascending'
+     *                                            ),
+     *                                            'last_login' => array()
+     *                                        )
+     *                                    )
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createIndex($table, $name, $definition)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $table = $db->quoteIdentifier($table, true);
+        $name  = $db->getIndexName($name);
+        $query = "CREATE INDEX $name ON $table";
+        $fields = array();
+        foreach ($definition['fields'] as $field_name => $field) {
+            $field_string = $field_name;
+            if (!empty($field['sorting'])) {
+                switch ($field['sorting']) {
+                case 'ascending':
+                    $field_string.= ' ASC';
+                    break;
+                case 'descending':
+                    $field_string.= ' DESC';
+                    break;
+                }
+            }
+            $fields[] = $field_string;
+        }
+        $query .= ' ('.implode(', ', $fields) . ')';
+        return $db->exec($query);
+    }
+
+    // }}}
+    // {{{ dropIndex()
+
+    /**
+     * drop existing index
+     *
+     * @param string    $table         name of table that should be used in method
+     * @param string    $name         name of the index to be dropped
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropIndex($table, $name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $name = $db->getIndexName($name);
+        return $db->exec("DROP INDEX $name");
+    }
+
+    // }}}
+    // {{{ listTableIndexes()
+
+    /**
+     * list all indexes in a table
+     *
+     * @param string $table name of table that should be used in method
+     * @return mixed array of index names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableIndexes($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $table = $db->quote($table, 'text');
+        $query = "SELECT sql FROM sqlite_master WHERE type='index' AND ";
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $query.= 'LOWER(tbl_name)='.strtolower($table);
+        } else {
+            $query.= "tbl_name=$table";
+        }
+        $query.= " AND sql NOT NULL ORDER BY name";
+        $indexes = $db->queryCol($query, 'text');
+        if (PEAR::isError($indexes)) {
+            return $indexes;
+        }
+
+        $result = array();
+        foreach ($indexes as $sql) {
+            if (preg_match("/^create index ([^ ]+) on /i", $sql, $tmp)) {
+                $index = $this->_fixIndexName($tmp[1]);
+                if (!empty($index)) {
+                    $result[$index] = true;
+                }
+            }
+        }
+
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_change_key_case($result, $db->options['field_case']);
+        }
+        return array_keys($result);
+    }
+
+    // }}}
+    // {{{ createConstraint()
+
+    /**
+     * create a constraint on a table
+     *
+     * @param string    $table         name of the table on which the constraint is to be created
+     * @param string    $name         name of the constraint to be created
+     * @param array     $definition        associative array that defines properties of the constraint to be created.
+     *                                 Currently, only one property named FIELDS is supported. This property
+     *                                 is also an associative with the names of the constraint fields as array
+     *                                 constraints. Each entry of this array is set to another type of associative
+     *                                 array that specifies properties of the constraint that are specific to
+     *                                 each field.
+     *
+     *                                 Example
+     *                                    array(
+     *                                        'fields' => array(
+     *                                            'user_name' => array(),
+     *                                            'last_login' => array()
+     *                                        )
+     *                                    )
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createConstraint($table, $name, $definition)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        if (!empty($definition['primary'])) {
+            return $db->manager->alterTable($table, array(), false, array('primary' => $definition['fields']));
+        }
+
+        $table = $db->quoteIdentifier($table, true);
+        $name  = $db->getIndexName($name);
+        $query = "CREATE UNIQUE INDEX $name ON $table";
+        $fields = array();
+        foreach ($definition['fields'] as $field_name => $field) {
+            $field_string = $field_name;
+            if (!empty($field['sorting'])) {
+                switch ($field['sorting']) {
+                case 'ascending':
+                    $field_string.= ' ASC';
+                    break;
+                case 'descending':
+                    $field_string.= ' DESC';
+                    break;
+                }
+            }
+            $fields[] = $field_string;
+        }
+        $query .= ' ('.implode(', ', $fields) . ')';
+        return $db->exec($query);
+    }
+
+    // }}}
+    // {{{ dropConstraint()
+
+    /**
+     * drop existing constraint
+     *
+     * @param string    $table        name of table that should be used in method
+     * @param string    $name         name of the constraint to be dropped
+     * @param string    $primary      hint if the constraint is primary
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropConstraint($table, $name, $primary = false)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        if ($primary || $name == 'PRIMARY') {
+            return $db->manager->alterTable($table, array(), false, array('primary' => null));
+        }
+
+        $name = $db->getIndexName($name);
+        return $db->exec("DROP INDEX $name");
+    }
+
+    // }}}
+    // {{{ listTableConstraints()
+
+    /**
+     * list all constraints in a table
+     *
+     * @param string $table name of table that should be used in method
+     * @return mixed array of constraint names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listTableConstraints($table)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $table = $db->quote($table, 'text');
+        $query = "SELECT sql FROM sqlite_master WHERE type='index' AND ";
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $query.= 'LOWER(tbl_name)='.strtolower($table);
+        } else {
+            $query.= "tbl_name=$table";
+        }
+        $query.= " AND sql NOT NULL ORDER BY name";
+        $indexes = $db->queryCol($query, 'text');
+        if (PEAR::isError($indexes)) {
+            return $indexes;
+        }
+
+        $result = array();
+        foreach ($indexes as $sql) {
+            if (preg_match("/^create unique index ([^ ]+) on /i", $sql, $tmp)) {
+                $index = $this->_fixIndexName($tmp[1]);
+                if (!empty($index)) {
+                    $result[$index] = true;
+                }
+            }
+        }
+
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_change_key_case($result, $db->options['field_case']);
+        }
+        return array_keys($result);
+    }
+
+    // }}}
+    // {{{ createSequence()
+
+    /**
+     * create sequence
+     *
+     * @param string    $seq_name     name of the sequence to be created
+     * @param string    $start         start value of the sequence; default is 1
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function createSequence($seq_name, $start = 1)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
+        $seqcol_name = $db->quoteIdentifier($db->options['seqcol_name'], true);
+        $query = "CREATE TABLE $sequence_name ($seqcol_name INTEGER PRIMARY KEY DEFAULT 0 NOT NULL)";
+        $res = $db->exec($query);
+        if (PEAR::isError($res)) {
+            return $res;
+        }
+        if ($start == 1) {
+            return MDB2_OK;
+        }
+        $res = $db->exec("INSERT INTO $sequence_name ($seqcol_name) VALUES (".($start-1).')');
+        if (!PEAR::isError($res)) {
+            return MDB2_OK;
+        }
+        // Handle error
+        $result = $db->exec("DROP TABLE $sequence_name");
+        if (PEAR::isError($result)) {
+            return $db->raiseError($result, null, null,
+                'could not drop inconsistent sequence table', __FUNCTION__);
+        }
+        return $db->raiseError($res, null, null,
+            'could not create sequence table', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ dropSequence()
+
+    /**
+     * drop existing sequence
+     *
+     * @param string    $seq_name     name of the sequence to be dropped
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function dropSequence($seq_name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
+        return $db->exec("DROP TABLE $sequence_name");
+    }
+
+    // }}}
+    // {{{ listSequences()
+
+    /**
+     * list all sequences in the current database
+     *
+     * @return mixed array of sequence names on success, a MDB2 error on failure
+     * @access public
+     */
+    function listSequences()
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = "SELECT name FROM sqlite_master WHERE type='table' AND sql NOT NULL ORDER BY name";
+        $table_names = $db->queryCol($query);
+        if (PEAR::isError($table_names)) {
+            return $table_names;
+        }
+        $result = array();
+        foreach ($table_names as $table_name) {
+            if ($sqn = $this->_fixSequenceName($table_name, true)) {
+                $result[] = $sqn;
+            }
+        }
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
+        }
+        return $result;
+    }
+
+    // }}}
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Native/Common.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Native/Common.php
new file mode 100644 (file)
index 0000000..3197d6d
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: Common.php,v 1.1 2006/06/18 21:59:05 lsmith Exp $
+//
+
+/**
+ * Base class for the natuve modules that is extended by each MDB2 driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_Native_Common extends MDB2_Module_Common
+{
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Native/mysql.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Native/mysql.php
new file mode 100644 (file)
index 0000000..90ff068
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: mysql.php,v 1.9 2006/06/18 21:59:05 lsmith Exp $
+//
+
+require_once 'MDB2/Driver/Native/Common.php';
+
+/**
+ * MDB2 MySQL driver for the native module
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_Native_mysql extends MDB2_Driver_Native_Common
+{
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Native/pgsql.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Native/pgsql.php
new file mode 100644 (file)
index 0000000..acab838
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Paul Cooper <pgc@ucecom.com>                                 |
+// +----------------------------------------------------------------------+
+//
+// $Id: pgsql.php,v 1.12 2006/07/15 13:07:15 lsmith Exp $
+
+require_once 'MDB2/Driver/Native/Common.php';
+
+/**
+ * MDB2 PostGreSQL driver for the native module
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Paul Cooper <pgc@ucecom.com>
+ */
+class MDB2_Driver_Native_pgsql extends MDB2_Driver_Native_Common
+{
+    // }}}
+    // {{{ deleteOID()
+
+    /**
+     * delete an OID
+     *
+     * @param integer    $OID
+     * @return mixed MDB2_OK on success or MDB2 Error Object on failure
+     * @access public
+     */
+    function deleteOID($OID)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $connection = $db->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+
+        if (!@pg_lo_unlink($connection, $OID)) {
+            return $db->raiseError(null, null, null,
+                'Unable to unlink OID: '.$OID, __FUNCTION__);
+        }
+        return MDB2_OK;
+    }
+
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Native/sqlite.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Native/sqlite.php
new file mode 100644 (file)
index 0000000..0213293
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: sqlite.php,v 1.9 2006/06/18 21:59:05 lsmith Exp $
+//
+
+require_once 'MDB2/Driver/Native/Common.php';
+
+/**
+ * MDB2 SQLite driver for the native module
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_Native_sqlite extends MDB2_Driver_Native_Common
+{
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Reverse/Common.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Reverse/Common.php
new file mode 100644 (file)
index 0000000..4c0dff3
--- /dev/null
@@ -0,0 +1,476 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: Common.php,v 1.35 2007/02/25 11:14:34 quipo Exp $
+//
+
+/**
+ * @package MDB2
+ * @category Database
+ */
+
+/**
+ * These are constants for the tableInfo-function
+ * they are bitwised or'ed. so if there are more constants to be defined
+ * in the future, adjust MDB2_TABLEINFO_FULL accordingly
+ */
+
+define('MDB2_TABLEINFO_ORDER',      1);
+define('MDB2_TABLEINFO_ORDERTABLE', 2);
+define('MDB2_TABLEINFO_FULL',       3);
+
+/**
+ * Base class for the schema reverse engineering module that is extended by each MDB2 driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_Reverse_Common extends MDB2_Module_Common
+{
+    // }}}
+    // {{{ getTableFieldDefinition()
+
+    /**
+     * Get the structure of a field into an array
+     *
+     * @param string    $table     name of table that should be used in method
+     * @param string    $field     name of field that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure.
+     *          The returned array contains an array for each field definition,
+     *          with all or some of these indices, depending on the field data type:
+     *          [notnull] [nativetype] [length] [fixed] [default] [type] [mdb2type]
+     * @access public
+     */
+    function getTableFieldDefinition($table, $field)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ getTableIndexDefinition()
+
+    /**
+     * Get the structure of an index into an array
+     *
+     * @param string    $table      name of table that should be used in method
+     * @param string    $index      name of index that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     *          The returned array has this structure:
+     *          </pre>
+     *          array (
+     *              [fields] => array (
+     *                  [field1name] => array() // one entry per each field covered
+     *                  [field2name] => array() // by the index
+     *                  [field3name] => array(
+     *                      [sorting] => ascending
+     *                  )
+     *              )
+     *          );
+     *          </pre>
+     * @access public
+     */
+    function getTableIndexDefinition($table, $index)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ getTableConstraintDefinition()
+
+    /**
+     * Get the structure of an constraints into an array
+     *
+     * @param string    $table      name of table that should be used in method
+     * @param string    $index      name of index that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     *          The returned array has this structure:
+     *          <pre>
+     *          array (
+     *              [primary] => 1
+     *              [fields] => array (
+     *                  [field1name] => array() // one entry per each field covered
+     *                  [field2name] => array() // by the index
+     *                  [field3name] => array(
+     *                      [sorting] => ascending
+     *                  )
+     *              )
+     *          );
+     *          </pre>
+     * @access public
+     */
+    function getTableConstraintDefinition($table, $index)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ getSequenceDefinition()
+
+    /**
+     * Get the structure of a sequence into an array
+     *
+     * @param string    $sequence   name of sequence that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     *          The returned array has this structure:
+     *          <pre>
+     *          array (
+     *              [start] => n
+     *          );
+     *          </pre>
+     * @access public
+     */
+    function getSequenceDefinition($sequence)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $start = $db->currId($sequence);
+        if (PEAR::isError($start)) {
+            return $start;
+        }
+        if ($db->supports('current_id')) {
+            $start++;
+        } else {
+            $db->warnings[] = 'database does not support getting current
+                sequence value, the sequence value was incremented';
+        }
+        $definition = array();
+        if ($start != 1) {
+            $definition = array('start' => $start);
+        }
+        return $definition;
+    }
+
+    // }}}
+    // {{{ getTriggerDefinition()
+
+    /**
+     * Get the structure of a trigger into an array
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change the returned value 
+     * at any time until labelled as non-experimental
+     *
+     * @param string    $trigger    name of trigger that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     *          The returned array has this structure:
+     *          <pre>
+     *          array (
+     *              [trigger_name]    => 'trigger name',
+     *              [table_name]      => 'table name',
+     *              [trigger_body]    => 'trigger body definition',
+     *              [trigger_type]    => 'BEFORE' | 'AFTER',
+     *              [trigger_event]   => 'INSERT' | 'UPDATE' | 'DELETE'
+     *                  //or comma separated list of multiple events, when supported
+     *              [trigger_enabled] => true|false
+     *              [trigger_comment] => 'trigger comment',
+     *          );
+     *          </pre>
+     *          The oci8 driver also returns a [when_clause] index.
+     * @access public
+     */
+    function getTriggerDefinition($trigger)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+            'method not implemented', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ tableInfo()
+
+    /**
+     * Returns information about a table or a result set
+     *
+     * The format of the resulting array depends on which <var>$mode</var>
+     * you select.  The sample output below is based on this query:
+     * <pre>
+     *    SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId
+     *    FROM tblFoo
+     *    JOIN tblBar ON tblFoo.fldId = tblBar.fldId
+     * </pre>
+     *
+     * <ul>
+     * <li>
+     *
+     * <kbd>null</kbd> (default)
+     *   <pre>
+     *   [0] => Array (
+     *       [table] => tblFoo
+     *       [name] => fldId
+     *       [type] => int
+     *       [len] => 11
+     *       [flags] => primary_key not_null
+     *   )
+     *   [1] => Array (
+     *       [table] => tblFoo
+     *       [name] => fldPhone
+     *       [type] => string
+     *       [len] => 20
+     *       [flags] =>
+     *   )
+     *   [2] => Array (
+     *       [table] => tblBar
+     *       [name] => fldId
+     *       [type] => int
+     *       [len] => 11
+     *       [flags] => primary_key not_null
+     *   )
+     *   </pre>
+     *
+     * </li><li>
+     *
+     * <kbd>MDB2_TABLEINFO_ORDER</kbd>
+     *
+     *   <p>In addition to the information found in the default output,
+     *   a notation of the number of columns is provided by the
+     *   <samp>num_fields</samp> element while the <samp>order</samp>
+     *   element provides an array with the column names as the keys and
+     *   their location index number (corresponding to the keys in the
+     *   the default output) as the values.</p>
+     *
+     *   <p>If a result set has identical field names, the last one is
+     *   used.</p>
+     *
+     *   <pre>
+     *   [num_fields] => 3
+     *   [order] => Array (
+     *       [fldId] => 2
+     *       [fldTrans] => 1
+     *   )
+     *   </pre>
+     *
+     * </li><li>
+     *
+     * <kbd>MDB2_TABLEINFO_ORDERTABLE</kbd>
+     *
+     *   <p>Similar to <kbd>MDB2_TABLEINFO_ORDER</kbd> but adds more
+     *   dimensions to the array in which the table names are keys and
+     *   the field names are sub-keys.  This is helpful for queries that
+     *   join tables which have identical field names.</p>
+     *
+     *   <pre>
+     *   [num_fields] => 3
+     *   [ordertable] => Array (
+     *       [tblFoo] => Array (
+     *           [fldId] => 0
+     *           [fldPhone] => 1
+     *       )
+     *       [tblBar] => Array (
+     *           [fldId] => 2
+     *       )
+     *   )
+     *   </pre>
+     *
+     * </li>
+     * </ul>
+     *
+     * The <samp>flags</samp> element contains a space separated list
+     * of extra information about the field.  This data is inconsistent
+     * between DBMS's due to the way each DBMS works.
+     *   + <samp>primary_key</samp>
+     *   + <samp>unique_key</samp>
+     *   + <samp>multiple_key</samp>
+     *   + <samp>not_null</samp>
+     *
+     * Most DBMS's only provide the <samp>table</samp> and <samp>flags</samp>
+     * elements if <var>$result</var> is a table name.  The following DBMS's
+     * provide full information from queries:
+     *   + fbsql
+     *   + mysql
+     *
+     * If the 'portability' option has <samp>MDB2_PORTABILITY_FIX_CASE</samp>
+     * turned on, the names of tables and fields will be lower or upper cased.
+     *
+     * @param object|string  $result  MDB2_result object from a query or a
+     *                                string containing the name of a table.
+     *                                While this also accepts a query result
+     *                                resource identifier, this behavior is
+     *                                deprecated.
+     * @param int  $mode   either unused or one of the tableInfo modes:
+     *                     <kbd>MDB2_TABLEINFO_ORDERTABLE</kbd>,
+     *                     <kbd>MDB2_TABLEINFO_ORDER</kbd> or
+     *                     <kbd>MDB2_TABLEINFO_FULL</kbd> (which does both).
+     *                     These are bitwise, so the first two can be
+     *                     combined using <kbd>|</kbd>.
+     *
+     * @return array  an associative array with the information requested.
+     *                 A MDB2_Error object on failure.
+     *
+     * @see MDB2_Driver_Common::setOption()
+     */
+    function tableInfo($result, $mode = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        if (!is_string($result)) {
+            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'method not implemented', __FUNCTION__);
+        }
+
+        $db->loadModule('Manager', null, true);
+        $fields = $db->manager->listTableFields($result);
+        if (PEAR::isError($fields)) {
+            return $fields;
+        }
+
+        $flags = array();
+
+        $idxname_format = $db->getOption('idxname_format');
+        $db->setOption('idxname_format', '%s');
+
+        $indexes = $db->manager->listTableIndexes($result);
+        if (PEAR::isError($indexes)) {
+            $db->setOption('idxname_format', $idxname_format);
+            return $indexes;
+        }
+
+        foreach ($indexes as $index) {
+            $definition = $this->getTableIndexDefinition($result, $index);
+            if (PEAR::isError($definition)) {
+                $db->setOption('idxname_format', $idxname_format);
+                return $definition;
+            }
+            if (count($definition['fields']) > 1) {
+                foreach ($definition['fields'] as $field => $sort) {
+                    $flags[$field] = 'multiple_key';
+                }
+            }
+        }
+
+        $constraints = $db->manager->listTableConstraints($result);
+        if (PEAR::isError($constraints)) {
+            return $constraints;
+        }
+
+        foreach ($constraints as $constraint) {
+            $definition = $this->getTableConstraintDefinition($result, $constraint);
+            if (PEAR::isError($definition)) {
+                $db->setOption('idxname_format', $idxname_format);
+                return $definition;
+            }
+            $flag = !empty($definition['primary'])
+                ? 'primary_key' : (!empty($definition['unique'])
+                    ? 'unique_key' : false);
+            if ($flag) {
+                foreach ($definition['fields'] as $field => $sort) {
+                    if (empty($flags[$field]) || $flags[$field] != 'primary_key') {
+                        $flags[$field] = $flag;
+                    }
+                }
+            }
+        }
+
+        if ($mode) {
+            $res['num_fields'] = count($fields);
+        }
+
+        foreach ($fields as $i => $field) {
+            $definition = $this->getTableFieldDefinition($result, $field);
+            if (PEAR::isError($definition)) {
+                $db->setOption('idxname_format', $idxname_format);
+                return $definition;
+            }
+            $res[$i] = $definition[0];
+            $res[$i]['name'] = $field;
+            $res[$i]['table'] = $result;
+            $res[$i]['type'] = preg_replace('/^([a-z]+).*$/i', '\\1', trim($definition[0]['nativetype']));
+            // 'primary_key', 'unique_key', 'multiple_key'
+            $res[$i]['flags'] = empty($flags[$field]) ? '' : $flags[$field];
+            // not_null', 'unsigned', 'auto_increment', 'default_[rawencodedvalue]'
+            if (!empty($res[$i]['notnull'])) {
+                $res[$i]['flags'].= ' not_null';
+            }
+            if (!empty($res[$i]['unsigned'])) {
+                $res[$i]['flags'].= ' unsigned';
+            }
+            if (!empty($res[$i]['auto_increment'])) {
+                $res[$i]['flags'].= ' autoincrement';
+            }
+            if (!empty($res[$i]['default'])) {
+                $res[$i]['flags'].= ' default_'.rawurlencode($res[$i]['default']);
+            }
+
+            if ($mode & MDB2_TABLEINFO_ORDER) {
+                $res['order'][$res[$i]['name']] = $i;
+            }
+            if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
+                $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
+            }
+        }
+
+        $db->setOption('idxname_format', $idxname_format);
+        return $res;
+    }
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Reverse/mysql.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Reverse/mysql.php
new file mode 100644 (file)
index 0000000..45a3777
--- /dev/null
@@ -0,0 +1,437 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: mysql.php,v 1.68 2007/03/29 18:18:06 quipo Exp $
+//
+
+require_once 'MDB2/Driver/Reverse/Common.php';
+
+/**
+ * MDB2 MySQL driver for the schema reverse engineering module
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ * @author  Lorenzo Alberton <l.alberton@quipo.it>
+ */
+class MDB2_Driver_Reverse_mysql extends MDB2_Driver_Reverse_Common
+{
+    // {{{ getTableFieldDefinition()
+
+    /**
+     * Get the structure of a field into an array
+     *
+     * @param string    $table       name of table that should be used in method
+     * @param string    $field_name  name of field that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     * @access public
+     */
+    function getTableFieldDefinition($table, $field_name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $result = $db->loadModule('Datatype', null, true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        $table = $db->quoteIdentifier($table, true);
+        $query = "SHOW COLUMNS FROM $table LIKE ".$db->quote($field_name);
+        $columns = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
+        if (PEAR::isError($columns)) {
+            return $columns;
+        }
+        foreach ($columns as $column) {
+            $column = array_change_key_case($column, CASE_LOWER);
+            $column['name'] = $column['field'];
+            unset($column['field']);
+            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+                if ($db->options['field_case'] == CASE_LOWER) {
+                    $column['name'] = strtolower($column['name']);
+                } else {
+                    $column['name'] = strtoupper($column['name']);
+                }
+            } else {
+                $column = array_change_key_case($column, $db->options['field_case']);
+            }
+            if ($field_name == $column['name']) {
+                $mapped_datatype = $db->datatype->mapNativeDatatype($column);
+                if (PEAR::IsError($mapped_datatype)) {
+                    return $mapped_datatype;
+                }
+                list($types, $length, $unsigned, $fixed) = $mapped_datatype;
+                $notnull = false;
+                if (empty($column['null']) || $column['null'] !== 'YES') {
+                    $notnull = true;
+                }
+                $default = false;
+                if (array_key_exists('default', $column)) {
+                    $default = $column['default'];
+                    if (is_null($default) && $notnull) {
+                        $default = '';
+                    }
+                }
+                $autoincrement = false;
+                if (!empty($column['extra']) && $column['extra'] == 'auto_increment') {
+                    $autoincrement = true;
+                }
+
+                $definition[0] = array(
+                    'notnull' => $notnull,
+                    'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
+                );
+                if (!is_null($length)) {
+                    $definition[0]['length'] = $length;
+                }
+                if (!is_null($unsigned)) {
+                    $definition[0]['unsigned'] = $unsigned;
+                }
+                if (!is_null($fixed)) {
+                    $definition[0]['fixed'] = $fixed;
+                }
+                if ($default !== false) {
+                    $definition[0]['default'] = $default;
+                }
+                if ($autoincrement !== false) {
+                    $definition[0]['autoincrement'] = $autoincrement;
+                }
+                foreach ($types as $key => $type) {
+                    $definition[$key] = $definition[0];
+                    if ($type == 'clob' || $type == 'blob') {
+                        unset($definition[$key]['default']);
+                    }
+                    $definition[$key]['type'] = $type;
+                    $definition[$key]['mdb2type'] = $type;
+                }
+                return $definition;
+            }
+        }
+
+        return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+            'it was not specified an existing table column', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ getTableIndexDefinition()
+
+    /**
+     * Get the structure of an index into an array
+     *
+     * @param string    $table      name of table that should be used in method
+     * @param string    $constraint_name name of constraint that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     * @access public
+     */
+    function getTableIndexDefinition($table, $constraint_name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $table = $db->quoteIdentifier($table, true);
+        $query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
+        $constraint_name_mdb2 = $db->getIndexName($constraint_name);
+        $result = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2)));
+        if (!PEAR::isError($result) && !is_null($result)) {
+            // apply 'idxname_format' only if the query succeeded, otherwise
+            // fallback to the given $index_name, without transformation
+            $constraint_name = $constraint_name_mdb2;
+        }
+        $result = $db->query(sprintf($query, $db->quote($constraint_name)));
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        $colpos = 1;
+        $definition = array();
+        while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
+            $row = array_change_key_case($row, CASE_LOWER);
+            $key_name = $row['key_name'];
+            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+                if ($db->options['field_case'] == CASE_LOWER) {
+                    $key_name = strtolower($key_name);
+                } else {
+                    $key_name = strtoupper($key_name);
+                }
+            }
+            if ($constraint_name == $key_name) {
+                if (!$row['non_unique']) {
+                    return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                        $constraint_name . ' is not an existing table constraint', __FUNCTION__);
+                }
+                $column_name = $row['column_name'];
+                if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+                    if ($db->options['field_case'] == CASE_LOWER) {
+                        $column_name = strtolower($column_name);
+                    } else {
+                        $column_name = strtoupper($column_name);
+                    }
+                }
+                $definition['fields'][$column_name] = array(
+                    'position' => $colpos++
+                );
+                if (!empty($row['collation'])) {
+                    $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
+                        ? 'ascending' : 'descending');
+                }
+            }
+        }
+        $result->free();
+        if (empty($definition['fields'])) {
+            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                $constraint_name . ' is not an existing table constraint', __FUNCTION__);
+        }
+        return $definition;
+    }
+
+    // }}}
+    // {{{ getTableConstraintDefinition()
+
+    /**
+     * Get the structure of a constraint into an array
+     *
+     * @param string    $table      name of table that should be used in method
+     * @param string    $index_name name of index that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     * @access public
+     */
+    function getTableConstraintDefinition($table, $index_name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $table = $db->quoteIdentifier($table, true);
+        $query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
+        if (strtolower($index_name) != 'primary') {
+            $index_name_mdb2 = $db->getIndexName($index_name);
+            $result = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2)));
+            if (!PEAR::isError($result) && !is_null($result)) {
+                // apply 'idxname_format' only if the query succeeded, otherwise
+                // fallback to the given $index_name, without transformation
+                $index_name = $index_name_mdb2;
+            }
+        }
+        $result = $db->query(sprintf($query, $db->quote($index_name)));
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        $colpos = 1;
+        $definition = array();
+        while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
+            $row = array_change_key_case($row, CASE_LOWER);
+            $key_name = $row['key_name'];
+            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+                if ($db->options['field_case'] == CASE_LOWER) {
+                    $key_name = strtolower($key_name);
+                } else {
+                    $key_name = strtoupper($key_name);
+                }
+            }
+            if ($index_name == $key_name) {
+                if ($row['non_unique']) {
+                    return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                        'it was not specified an existing table constraint', __FUNCTION__);
+                }
+                if ($row['key_name'] == 'PRIMARY') {
+                    $definition['primary'] = true;
+                } else {
+                    $definition['unique'] = true;
+                }
+                $column_name = $row['column_name'];
+                if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+                    if ($db->options['field_case'] == CASE_LOWER) {
+                        $column_name = strtolower($column_name);
+                    } else {
+                        $column_name = strtoupper($column_name);
+                    }
+                }
+                $definition['fields'][$column_name] = array(
+                    'position' => $colpos++
+                );
+                if (!empty($row['collation'])) {
+                    $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
+                        ? 'ascending' : 'descending');
+                }
+            }
+        }
+        $result->free();
+        if (empty($definition['fields'])) {
+            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'it was not specified an existing table constraint', __FUNCTION__);
+        }
+        return $definition;
+    }
+
+    // }}}
+    // {{{ getTriggerDefinition()
+
+    /**
+     * Get the structure of a trigger into an array
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change the returned value
+     * at any time until labelled as non-experimental
+     *
+     * @param string    $trigger    name of trigger that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     * @access public
+     */
+    function getTriggerDefinition($trigger)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = 'SELECT trigger_name,
+                         event_object_table AS table_name,
+                         action_statement AS trigger_body,
+                         action_timing AS trigger_type,
+                         event_manipulation AS trigger_event
+                    FROM information_schema.triggers
+                   WHERE trigger_name = '. $db->quote($trigger, 'text');
+        $types = array(
+            'trigger_name'    => 'text',
+            'table_name'      => 'text',
+            'trigger_body'    => 'text',
+            'trigger_type'    => 'text',
+            'trigger_event'   => 'text',
+        );
+        $def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
+        if (PEAR::isError($def)) {
+            return $def;
+        }
+        $def['trigger_comment'] = '';
+        $def['trigger_enabled'] = true;
+        return $def;
+    }
+
+    // }}}
+    // {{{ tableInfo()
+
+    /**
+     * Returns information about a table or a result set
+     *
+     * @param object|string  $result  MDB2_result object from a query or a
+     *                                 string containing the name of a table.
+     *                                 While this also accepts a query result
+     *                                 resource identifier, this behavior is
+     *                                 deprecated.
+     * @param int            $mode    a valid tableInfo mode
+     *
+     * @return array  an associative array with the information requested.
+     *                 A MDB2_Error object on failure.
+     *
+     * @see MDB2_Driver_Common::setOption()
+     */
+    function tableInfo($result, $mode = null)
+    {
+        if (is_string($result)) {
+           return parent::tableInfo($result, $mode);
+        }
+
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $resource = MDB2::isResultCommon($result) ? $result->getResource() : $result;
+        if (!is_resource($resource)) {
+            return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                'Could not generate result resource', __FUNCTION__);
+        }
+
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            if ($db->options['field_case'] == CASE_LOWER) {
+                $case_func = 'strtolower';
+            } else {
+                $case_func = 'strtoupper';
+            }
+        } else {
+            $case_func = 'strval';
+        }
+
+        $count = @mysql_num_fields($resource);
+        $res   = array();
+
+        if ($mode) {
+            $res['num_fields'] = $count;
+        }
+
+        $db->loadModule('Datatype', null, true);
+        for ($i = 0; $i < $count; $i++) {
+            $res[$i] = array(
+                'table' => $case_func(@mysql_field_table($resource, $i)),
+                'name'  => $case_func(@mysql_field_name($resource, $i)),
+                'type'  => @mysql_field_type($resource, $i),
+                'length'   => @mysql_field_len($resource, $i),
+                'flags' => @mysql_field_flags($resource, $i),
+            );
+            if ($res[$i]['type'] == 'string') {
+                $res[$i]['type'] = 'char';
+            } elseif ($res[$i]['type'] == 'unknown') {
+                $res[$i]['type'] = 'decimal';
+            }
+            $mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]);
+            if (PEAR::isError($mdb2type_info)) {
+               return $mdb2type_info;
+            }
+            $res[$i]['mdb2type'] = $mdb2type_info[0][0];
+            if ($mode & MDB2_TABLEINFO_ORDER) {
+                $res['order'][$res[$i]['name']] = $i;
+            }
+            if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
+                $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
+            }
+        }
+
+        return $res;
+    }
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Reverse/pgsql.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Reverse/pgsql.php
new file mode 100644 (file)
index 0000000..3e16681
--- /dev/null
@@ -0,0 +1,439 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Authors: Paul Cooper <pgc@ucecom.com>                                |
+// |          Lorenzo Alberton <l.alberton@quipo.it>                      |
+// +----------------------------------------------------------------------+
+//
+// $Id: pgsql.php,v 1.60 2007/03/29 18:18:06 quipo Exp $
+
+require_once 'MDB2/Driver/Reverse/Common.php';
+
+/**
+ * MDB2 PostGreSQL driver for the schema reverse engineering module
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Paul Cooper <pgc@ucecom.com>
+ */
+class MDB2_Driver_Reverse_pgsql extends MDB2_Driver_Reverse_Common
+{
+    // {{{ getTableFieldDefinition()
+
+    /**
+     * Get the structure of a field into an array
+     *
+     * @param string    $table       name of table that should be used in method
+     * @param string    $field_name  name of field that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     * @access public
+     */
+    function getTableFieldDefinition($table, $field_name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $result = $db->loadModule('Datatype', null, true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+
+        $query = "SELECT a.attname AS name,
+                         t.typname AS type,
+                         CASE a.attlen
+                           WHEN -1 THEN
+                                CASE t.typname
+                                  WHEN 'numeric' THEN (a.atttypmod / 65536)
+                                  WHEN 'decimal' THEN (a.atttypmod / 65536)
+                                  WHEN 'money'   THEN (a.atttypmod / 65536)
+                                  ELSE CASE a.atttypmod
+                                 WHEN -1 THEN NULL
+                                    ELSE a.atttypmod - 4
+                                  END
+                             END
+                              ELSE a.attlen
+                         END AS length,
+                            CASE t.typname
+                              WHEN 'numeric' THEN (a.atttypmod % 65536) - 4
+                              WHEN 'decimal' THEN (a.atttypmod % 65536) - 4
+                              WHEN 'money'   THEN (a.atttypmod % 65536) - 4
+                              ELSE 0
+                         END AS scale,
+                         a.attnotnull,
+                         a.atttypmod,
+                         a.atthasdef,
+                         (SELECT substring(pg_get_expr(d.adbin, d.adrelid) for 128)
+                            FROM pg_attrdef d
+                           WHERE d.adrelid = a.attrelid
+                             AND d.adnum = a.attnum
+                             AND a.atthasdef
+                         ) as default
+                    FROM pg_attribute a,
+                         pg_class c,
+                         pg_type t
+                   WHERE c.relname = ".$db->quote($table, 'text')."
+                     AND a.atttypid = t.oid
+                     AND c.oid = a.attrelid
+                     AND NOT a.attisdropped
+                     AND a.attnum > 0
+                     AND a.attname = ".$db->quote($field_name, 'text')."
+                ORDER BY a.attnum";
+        $column = $db->queryRow($query, null, MDB2_FETCHMODE_ASSOC);
+        if (PEAR::isError($column)) {
+            return $column;
+        }
+
+        if (empty($column)) {
+            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'it was not specified an existing table column', __FUNCTION__);
+        }
+
+        $column = array_change_key_case($column, CASE_LOWER);
+        $mapped_datatype = $db->datatype->mapNativeDatatype($column);
+        if (PEAR::IsError($mapped_datatype)) {
+            return $mapped_datatype;
+        }
+        list($types, $length, $unsigned, $fixed) = $mapped_datatype;
+        $notnull = false;
+        if (!empty($column['attnotnull']) && $column['attnotnull'] == 't') {
+            $notnull = true;
+        }
+        $default = null;
+        if ($column['atthasdef'] === 't'
+            && !preg_match("/nextval\('([^']+)'/", $column['default'])
+        ) {
+            $default = $column['default'];#substr($column['adsrc'], 1, -1);
+            if (is_null($default) && $notnull) {
+                $default = '';
+            }
+        }
+        $autoincrement = false;
+        if (preg_match("/nextval\('([^']+)'/", $column['default'], $nextvals)) {
+            $autoincrement = true;
+        }
+        $definition[0] = array('notnull' => $notnull, 'nativetype' => $column['type']);
+        if (!is_null($length)) {
+            $definition[0]['length'] = $length;
+        }
+        if (!is_null($unsigned)) {
+            $definition[0]['unsigned'] = $unsigned;
+        }
+        if (!is_null($fixed)) {
+            $definition[0]['fixed'] = $fixed;
+        }
+        if ($default !== false) {
+            $definition[0]['default'] = $default;
+        }
+        if ($autoincrement !== false) {
+            $definition[0]['autoincrement'] = $autoincrement;
+        }
+        foreach ($types as $key => $type) {
+            $definition[$key] = $definition[0];
+            if ($type == 'clob' || $type == 'blob') {
+                unset($definition[$key]['default']);
+            }
+            $definition[$key]['type'] = $type;
+            $definition[$key]['mdb2type'] = $type;
+        }
+        return $definition;
+    }
+
+    // }}}
+    // {{{ getTableIndexDefinition()
+    /**
+     * Get the structure of an index into an array
+     *
+     * @param string    $table      name of table that should be used in method
+     * @param string    $index_name name of index that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     * @access public
+     */
+    function getTableIndexDefinition($table, $index_name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = 'SELECT relname, indkey FROM pg_index, pg_class';
+        $query.= ' WHERE pg_class.oid = pg_index.indexrelid';
+        $query.= " AND indisunique != 't' AND indisprimary != 't'";
+        $query.= ' AND pg_class.relname = %s';
+        $index_name_mdb2 = $db->getIndexName($index_name);
+        $row = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
+        if (PEAR::isError($row) || empty($row)) {
+            // fallback to the given $index_name, without transformation
+            $row = $db->queryRow(sprintf($query, $db->quote($index_name, 'text')), null, MDB2_FETCHMODE_ASSOC);
+        }
+        if (PEAR::isError($row)) {
+            return $row;
+        }
+
+        if (empty($row)) {
+            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'it was not specified an existing table index', __FUNCTION__);
+        }
+
+        $row = array_change_key_case($row, CASE_LOWER);
+
+        $db->loadModule('Manager', null, true);
+        $columns = $db->manager->listTableFields($table);
+
+        $definition = array();
+
+        $index_column_numbers = explode(' ', $row['indkey']);
+
+        $colpos = 1;
+        foreach ($index_column_numbers as $number) {
+            $definition['fields'][$columns[($number - 1)]] = array(
+                'position' => $colpos++,
+                'sorting' => 'ascending',
+            );
+        }
+        return $definition;
+    }
+
+    // }}}
+    // {{{ getTableConstraintDefinition()
+    /**
+     * Get the structure of a constraint into an array
+     *
+     * @param string    $table      name of table that should be used in method
+     * @param string    $constraint_name name of constraint that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     * @access public
+     */
+    function getTableConstraintDefinition($table, $constraint_name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+        
+        $query = 'SELECT relname, indisunique, indisprimary, indkey FROM pg_index, pg_class';
+        $query.= ' WHERE pg_class.oid = pg_index.indexrelid';
+        $query.= " AND (indisunique = 't' OR indisprimary = 't')";
+        $query.= ' AND pg_class.relname = %s';
+        $constraint_name_mdb2 = $db->getIndexName($constraint_name);
+        $row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
+        if (PEAR::isError($row) || empty($row)) {
+            // fallback to the given $index_name, without transformation
+            $row = $db->queryRow(sprintf($query, $db->quote($constraint_name, 'text')), null, MDB2_FETCHMODE_ASSOC);
+        }
+        if (PEAR::isError($row)) {
+            return $row;
+        }
+
+        if (empty($row)) {
+            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                $constraint_name . ' is not an existing table constraint', __FUNCTION__);
+        }
+
+        $row = array_change_key_case($row, CASE_LOWER);
+
+        $db->loadModule('Manager', null, true);
+        $columns = $db->manager->listTableFields($table);
+
+        $definition = array();
+        if ($row['indisprimary'] == 't') {
+            $definition['primary'] = true;
+        } elseif ($row['indisunique'] == 't') {
+            $definition['unique'] = true;
+        }
+
+        $index_column_numbers = explode(' ', $row['indkey']);
+
+        $colpos = 1;
+        foreach ($index_column_numbers as $number) {
+            $definition['fields'][$columns[($number - 1)]] = array(
+                'position' => $colpos++,
+                'sorting' => 'ascending',
+            );
+        }
+        return $definition;
+    }
+
+    // }}}
+    // {{{ getTriggerDefinition()
+
+    /**
+     * Get the structure of a trigger into an array
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change the returned value
+     * at any time until labelled as non-experimental
+     *
+     * @param string    $trigger    name of trigger that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     * @access public
+     *
+     * @TODO: add support for plsql functions and functions with args
+     */
+    function getTriggerDefinition($trigger)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = "SELECT trg.tgname AS trigger_name,
+                         tbl.relname AS table_name,
+                         CASE
+                            WHEN p.proname IS NOT NULL THEN 'EXECUTE PROCEDURE ' || p.proname || '();'
+                            ELSE ''
+                         END AS trigger_body,
+                         CASE trg.tgtype & cast(2 as int2)
+                            WHEN 0 THEN 'AFTER'
+                            ELSE 'BEFORE'
+                         END AS trigger_type,
+                         CASE trg.tgtype & cast(28 as int2)
+                            WHEN 16 THEN 'UPDATE'
+                            WHEN 8 THEN 'DELETE'
+                            WHEN 4 THEN 'INSERT'
+                            WHEN 20 THEN 'INSERT, UPDATE'
+                            WHEN 28 THEN 'INSERT, UPDATE, DELETE'
+                            WHEN 24 THEN 'UPDATE, DELETE'
+                            WHEN 12 THEN 'INSERT, DELETE'
+                         END AS trigger_event,
+                         trg.tgenabled AS trigger_enabled,
+                         obj_description(trg.oid, 'pg_trigger') AS trigger_comment
+                    FROM pg_trigger trg,
+                         pg_class tbl,
+                         pg_proc p
+                   WHERE trg.tgrelid = tbl.oid
+                     AND trg.tgfoid = p.oid
+                     AND trg.tgname = ". $db->quote($trigger, 'text');
+        $types = array(
+            'trigger_name'    => 'text',
+            'table_name'      => 'text',
+            'trigger_body'    => 'text',
+            'trigger_type'    => 'text',
+            'trigger_event'   => 'text',
+            'trigger_comment' => 'text',
+            'trigger_enabled' => 'boolean',
+        );
+        return $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
+    }
+    
+    // }}}
+    // {{{ tableInfo()
+
+    /**
+     * Returns information about a table or a result set
+     *
+     * NOTE: only supports 'table' and 'flags' if <var>$result</var>
+     * is a table name.
+     *
+     * @param object|string  $result  MDB2_result object from a query or a
+     *                                 string containing the name of a table.
+     *                                 While this also accepts a query result
+     *                                 resource identifier, this behavior is
+     *                                 deprecated.
+     * @param int            $mode    a valid tableInfo mode
+     *
+     * @return array  an associative array with the information requested.
+     *                 A MDB2_Error object on failure.
+     *
+     * @see MDB2_Driver_Common::tableInfo()
+     */
+    function tableInfo($result, $mode = null)
+    {
+        if (is_string($result)) {
+           return parent::tableInfo($result, $mode);
+        }
+
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $resource = MDB2::isResultCommon($result) ? $result->getResource() : $result;
+        if (!is_resource($resource)) {
+            return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                'Could not generate result resource', __FUNCTION__);
+        }
+
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            if ($db->options['field_case'] == CASE_LOWER) {
+                $case_func = 'strtolower';
+            } else {
+                $case_func = 'strtoupper';
+            }
+        } else {
+            $case_func = 'strval';
+        }
+
+        $count = @pg_num_fields($resource);
+        $res   = array();
+
+        if ($mode) {
+            $res['num_fields'] = $count;
+        }
+
+        $db->loadModule('Datatype', null, true);
+        for ($i = 0; $i < $count; $i++) {
+            $res[$i] = array(
+                'table' => function_exists('pg_field_table') ? @pg_field_table($resource, $i) : '',
+                'name'  => $case_func(@pg_field_name($resource, $i)),
+                'type'  => @pg_field_type($resource, $i),
+                'length' => @pg_field_size($resource, $i),
+                'flags' => '',
+            );
+            $mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]);
+            if (PEAR::isError($mdb2type_info)) {
+               return $mdb2type_info;
+            }
+            $res[$i]['mdb2type'] = $mdb2type_info[0][0];
+            if ($mode & MDB2_TABLEINFO_ORDER) {
+                $res['order'][$res[$i]['name']] = $i;
+            }
+            if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
+                $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
+            }
+        }
+
+        return $res;
+    }
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Reverse/sqlite.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/Reverse/sqlite.php
new file mode 100644 (file)
index 0000000..7f5ec38
--- /dev/null
@@ -0,0 +1,503 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: sqlite.php,v 1.70 2007/03/29 18:18:06 quipo Exp $
+//
+
+require_once 'MDB2/Driver/Reverse/Common.php';
+
+/**
+ * MDB2 SQlite driver for the schema reverse engineering module
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common
+{
+    function _getTableColumns($sql)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+        $start_pos = strpos($sql, '(');
+        $end_pos = strrpos($sql, ')');
+        $column_def = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
+        // replace the decimal length-places-separator with a colon
+        $column_def = preg_replace('/(\d),(\d)/', '\1:\2', $column_def);
+        $column_sql = split(',', $column_def);
+        $columns = array();
+        $count = count($column_sql);
+        if ($count == 0) {
+            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'unexpected empty table column definition list', __FUNCTION__);
+        }
+        $regexp = '/^([^ ]+) (CHAR|VARCHAR|VARCHAR2|TEXT|BOOLEAN|SMALLINT|INT|INTEGER|DECIMAL|BIGINT|DOUBLE|FLOAT|DATETIME|DATE|TIME|LONGTEXT|LONGBLOB)( ?\(([1-9][0-9]*)(:([1-9][0-9]*))?\))?( UNSIGNED)?( PRIMARY KEY)?( DEFAULT (\'[^\']*\'|[^ ]+))?( NULL| NOT NULL)?( PRIMARY KEY)?$/i';
+        $regexp2 = '/^([^ ]+) (PRIMARY|UNIQUE|CHECK)$/i';
+        for ($i=0, $j=0; $i<$count; ++$i) {
+            if (!preg_match($regexp, trim($column_sql[$i]), $matches)) {
+                if (!preg_match($regexp2, trim($column_sql[$i]))) {
+                    continue;
+                }
+                return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                    'unexpected table column SQL definition: "'.$column_sql[$i].'"', __FUNCTION__);
+            }
+            $columns[$j]['name'] = trim($matches[1], implode('', $db->identifier_quoting));
+            $columns[$j]['type'] = strtolower($matches[2]);
+            if (isset($matches[4]) && strlen($matches[4])) {
+                $columns[$j]['length'] = $matches[4];
+            }
+            if (isset($matches[6]) && strlen($matches[6])) {
+                $columns[$j]['decimal'] = $matches[6];
+            }
+            if (isset($matches[7]) && strlen($matches[7])) {
+                $columns[$j]['unsigned'] = true;
+            }
+            if (isset($matches[8]) && strlen($matches[8])) {
+                $columns[$j]['autoincrement'] = true;
+            }
+            if (isset($matches[10]) && strlen($matches[10])) {
+                $default = $matches[10];
+                if (strlen($default) && $default[0]=="'") {
+                    $default = str_replace("''", "'", substr($default, 1, strlen($default)-2));
+                }
+                if ($default === 'NULL') {
+                    $default = null;
+                }
+                $columns[$j]['default'] = $default;
+            }
+            if (isset($matches[11]) && strlen($matches[11])) {
+                $columns[$j]['notnull'] = ($matches[11] === ' NOT NULL');
+            }
+            ++$j;
+        }
+        return $columns;
+    }
+
+    // {{{ getTableFieldDefinition()
+
+    /**
+     * Get the stucture of a field into an array
+     *
+     * @param string    $table       name of table that should be used in method
+     * @param string    $field_name  name of field that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure.
+     *          The returned array contains an array for each field definition,
+     *          with (some of) these indices:
+     *          [notnull] [nativetype] [length] [fixed] [default] [type] [mdb2type]
+     * @access public
+     */
+    function getTableFieldDefinition($table, $field_name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $result = $db->loadModule('Datatype', null, true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        $query = "SELECT sql FROM sqlite_master WHERE type='table' AND ";
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text');
+        } else {
+            $query.= 'name='.$db->quote($table, 'text');
+        }
+        $sql = $db->queryOne($query);
+        if (PEAR::isError($sql)) {
+            return $sql;
+        }
+        $columns = $this->_getTableColumns($sql);
+        foreach ($columns as $column) {
+            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+                if ($db->options['field_case'] == CASE_LOWER) {
+                    $column['name'] = strtolower($column['name']);
+                } else {
+                    $column['name'] = strtoupper($column['name']);
+                }
+            } else {
+                $column = array_change_key_case($column, $db->options['field_case']);
+            }
+            if ($field_name == $column['name']) {
+                $mapped_datatype = $db->datatype->mapNativeDatatype($column);
+                if (PEAR::IsError($mapped_datatype)) {
+                    return $mapped_datatype;
+                }
+                list($types, $length, $unsigned, $fixed) = $mapped_datatype;
+                $notnull = false;
+                if (!empty($column['notnull'])) {
+                    $notnull = $column['notnull'];
+                }
+                $default = false;
+                if (array_key_exists('default', $column)) {
+                    $default = $column['default'];
+                    if (is_null($default) && $notnull) {
+                        $default = '';
+                    }
+                }
+                $autoincrement = false;
+                if (!empty($column['autoincrement'])) {
+                    $autoincrement = true;
+                }
+
+                $definition[0] = array(
+                    'notnull' => $notnull,
+                    'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
+                );
+                if (!is_null($length)) {
+                    $definition[0]['length'] = $length;
+                }
+                if (!is_null($unsigned)) {
+                    $definition[0]['unsigned'] = $unsigned;
+                }
+                if (!is_null($fixed)) {
+                    $definition[0]['fixed'] = $fixed;
+                }
+                if ($default !== false) {
+                    $definition[0]['default'] = $default;
+                }
+                if ($autoincrement !== false) {
+                    $definition[0]['autoincrement'] = $autoincrement;
+                }
+                foreach ($types as $key => $type) {
+                    $definition[$key] = $definition[0];
+                    if ($type == 'clob' || $type == 'blob') {
+                        unset($definition[$key]['default']);
+                    }
+                    $definition[$key]['type'] = $type;
+                    $definition[$key]['mdb2type'] = $type;
+                }
+                return $definition;
+            }
+        }
+
+        return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+            'it was not specified an existing table column', __FUNCTION__);
+    }
+
+    // }}}
+    // {{{ getTableIndexDefinition()
+
+    /**
+     * Get the stucture of an index into an array
+     *
+     * @param string    $table      name of table that should be used in method
+     * @param string    $index_name name of index that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     * @access public
+     */
+    function getTableIndexDefinition($table, $index_name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = "SELECT sql FROM sqlite_master WHERE type='index' AND ";
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $query.= 'LOWER(name)=%s AND LOWER(tbl_name)=' . $db->quote(strtolower($table), 'text');
+        } else {
+            $query.= 'name=%s AND tbl_name=' . $db->quote($table, 'text');
+        }
+        $query.= ' AND sql NOT NULL ORDER BY name';
+        $index_name_mdb2 = $db->getIndexName($index_name);
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $qry = sprintf($query, $db->quote(strtolower($index_name_mdb2), 'text'));
+        } else {
+            $qry = sprintf($query, $db->quote($index_name_mdb2, 'text'));
+        }
+        $sql = $db->queryOne($qry, 'text');
+        if (PEAR::isError($sql) || empty($sql)) {
+            // fallback to the given $index_name, without transformation
+            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+                $qry = sprintf($query, $db->quote(strtolower($index_name), 'text'));
+            } else {
+                $qry = sprintf($query, $db->quote($index_name, 'text'));
+            }
+            $sql = $db->queryOne($qry, 'text');
+        }
+        if (PEAR::isError($sql)) {
+            return $sql;
+        }
+        if (!$sql) {
+            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'it was not specified an existing table index', __FUNCTION__);
+        }
+
+        $sql = strtolower($sql);
+        $start_pos = strpos($sql, '(');
+        $end_pos = strrpos($sql, ')');
+        $column_names = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
+        $column_names = split(',', $column_names);
+
+        if (preg_match("/^create unique/", $sql)) {
+            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'it was not specified an existing table index', __FUNCTION__);
+        }
+
+        $definition = array();
+        $count = count($column_names);
+        for ($i=0; $i<$count; ++$i) {
+            $column_name = strtok($column_names[$i], ' ');
+            $collation = strtok(' ');
+            $definition['fields'][$column_name] = array(
+                'position' => $i+1
+            );
+            if (!empty($collation)) {
+                $definition['fields'][$column_name]['sorting'] =
+                    ($collation=='ASC' ? 'ascending' : 'descending');
+            }
+        }
+
+        if (empty($definition['fields'])) {
+            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'it was not specified an existing table index', __FUNCTION__);
+        }
+        return $definition;
+    }
+
+    // }}}
+    // {{{ getTableConstraintDefinition()
+
+    /**
+     * Get the stucture of a constraint into an array
+     *
+     * @param string    $table      name of table that should be used in method
+     * @param string    $constraint_name name of constraint that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     * @access public
+     */
+    function getTableConstraintDefinition($table, $constraint_name)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = "SELECT sql FROM sqlite_master WHERE type='index' AND ";
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $query.= 'LOWER(name)=%s AND LOWER(tbl_name)=' . $db->quote(strtolower($table), 'text');
+        } else {
+            $query.= 'name=%s AND tbl_name=' . $db->quote($table, 'text');
+        }
+        $query.= ' AND sql NOT NULL ORDER BY name';
+        $constraint_name_mdb2 = $db->getIndexName($constraint_name);
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $qry = sprintf($query, $db->quote(strtolower($constraint_name_mdb2), 'text'));
+        } else {
+            $qry = sprintf($query, $db->quote($constraint_name_mdb2, 'text'));
+        }
+        $sql = $db->queryOne($qry, 'text');
+        if (PEAR::isError($sql) || empty($sql)) {
+            // fallback to the given $index_name, without transformation
+            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+                $qry = sprintf($query, $db->quote(strtolower($constraint_name), 'text'));
+            } else {
+                $qry = sprintf($query, $db->quote($constraint_name, 'text'));
+            }
+            $sql = $db->queryOne($qry, 'text');
+        }
+        if (PEAR::isError($sql)) {
+            return $sql;
+        }
+        if (!$sql && $constraint_name == 'primary') {
+            // search in table definition for PRIMARY KEYs
+            $query = "SELECT sql FROM sqlite_master WHERE type='table' AND ";
+            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+                $query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text');
+            } else {
+                $query.= 'name='.$db->quote($table, 'text');
+            }
+            $query.= " AND sql NOT NULL ORDER BY name";
+            $sql = $db->queryOne($query, 'text');
+            if (PEAR::isError($sql)) {
+                return $sql;
+            }
+            if (preg_match("/\bPRIMARY\s+KEY\b\s*\(([^)]+)/i", $sql, $tmp)) {
+                $definition = array();
+                $definition['primary'] = true;
+                $definition['fields'] = array();
+                $column_names = split(',', $tmp[1]);
+                $colpos = 1;
+                foreach ($column_names as $column_name) {
+                    $definition['fields'][$column_name] = array(
+                        'position' => $colpos++
+                    );
+                }
+                return $definition;
+            }
+            $sql = false;
+        }
+        if (!$sql) {
+            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                $constraint_name . ' is not an existing table constraint', __FUNCTION__);
+        }
+
+        $sql = strtolower($sql);
+        $start_pos = strpos($sql, '(');
+        $end_pos = strrpos($sql, ')');
+        $column_names = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
+        $column_names = split(',', $column_names);
+
+        if (!preg_match("/^create unique/", $sql)) {
+            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                $constraint_name . ' is not an existing table constraint', __FUNCTION__);
+        }
+
+        $definition = array();
+        $definition['unique'] = true;
+        $count = count($column_names);
+        for ($i=0; $i<$count; ++$i) {
+            $column_name = strtok($column_names[$i]," ");
+            $collation = strtok(" ");
+            $definition['fields'][$column_name] = array(
+                'position' => $i+1
+            );
+            if (!empty($collation)) {
+                $definition['fields'][$column_name]['sorting'] =
+                    ($collation=='ASC' ? 'ascending' : 'descending');
+            }
+        }
+
+        if (empty($definition['fields'])) {
+            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                $constraint_name . ' is not an existing table constraint', __FUNCTION__);
+        }
+        return $definition;
+    }
+
+    // }}}
+    // {{{ getTriggerDefinition()
+
+    /**
+     * Get the structure of a trigger into an array
+     *
+     * EXPERIMENTAL
+     *
+     * WARNING: this function is experimental and may change the returned value
+     * at any time until labelled as non-experimental
+     *
+     * @param string    $trigger    name of trigger that should be used in method
+     * @return mixed data array on success, a MDB2 error on failure
+     * @access public
+     */
+    function getTriggerDefinition($trigger)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $query = "SELECT name as trigger_name,
+                         tbl_name AS table_name,
+                         sql AS trigger_body,
+                         NULL AS trigger_type,
+                         NULL AS trigger_event,
+                         NULL AS trigger_comment,
+                         1 AS trigger_enabled
+                    FROM sqlite_master
+                   WHERE type='trigger'";
+        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $query.= ' AND LOWER(name)='.$db->quote(strtolower($trigger), 'text');
+        } else {
+            $query.= ' AND name='.$db->quote($trigger, 'text');
+        }
+        $types = array(
+            'trigger_name'    => 'text',
+            'table_name'      => 'text',
+            'trigger_body'    => 'text',
+            'trigger_type'    => 'text',
+            'trigger_event'   => 'text',
+            'trigger_comment' => 'text',
+            'trigger_enabled' => 'boolean',
+        );
+        $def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
+        if (PEAR::isError($def)) {
+            return $def;
+        }
+        if (empty($def)) {
+            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'it was not specified an existing trigger', __FUNCTION__);
+        }
+        if (preg_match("/^create\s+(?:temp|temporary)?trigger\s+(?:if\s+not\s+exists\s+)?.*(before|after)?\s+(insert|update|delete)/Uims", $def['trigger_body'], $tmp)) {
+            $def['trigger_type'] = strtoupper($tmp[1]);
+            $def['trigger_event'] = strtoupper($tmp[2]);
+        }
+        return $def;
+    }
+
+    // }}}
+    // {{{ tableInfo()
+
+    /**
+     * Returns information about a table
+     *
+     * @param string         $result  a string containing the name of a table
+     * @param int            $mode    a valid tableInfo mode
+     *
+     * @return array  an associative array with the information requested.
+     *                 A MDB2_Error object on failure.
+     *
+     * @see MDB2_Driver_Common::tableInfo()
+     * @since Method available since Release 1.7.0
+     */
+    function tableInfo($result, $mode = null)
+    {
+        if (is_string($result)) {
+           return parent::tableInfo($result, $mode);
+        }
+
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        return $db->raiseError(MDB2_ERROR_NOT_CAPABLE, null, null,
+           'This DBMS can not obtain tableInfo from result sets', __FUNCTION__);
+    }
+}
+
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/mysql.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/mysql.php
new file mode 100644 (file)
index 0000000..baf2ba8
--- /dev/null
@@ -0,0 +1,1479 @@
+<?php
+// vim: set et ts=4 sw=4 fdm=marker:
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: mysql.php,v 1.182 2007/05/02 22:00:08 quipo Exp $
+//
+
+/**
+ * MDB2 MySQL driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_mysql extends MDB2_Driver_Common
+{
+    // {{{ properties
+    var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => '\\', 'escape_pattern' => '\\');
+
+    var $identifier_quoting = array('start' => '`', 'end' => '`', 'escape' => '`');
+
+    var $sql_comments = array(
+        array('start' => '-- ', 'end' => "\n", 'escape' => false),
+        array('start' => '#', 'end' => "\n", 'escape' => false),
+        array('start' => '/*', 'end' => '*/', 'escape' => false),
+    );
+
+    var $start_transaction = false;
+
+    var $varchar_max_length = 255;
+    // }}}
+    // {{{ constructor
+
+    /**
+     * Constructor
+     */
+    function __construct()
+    {
+        parent::__construct();
+
+        $this->phptype = 'mysql';
+        $this->dbsyntax = 'mysql';
+
+        $this->supported['sequences'] = 'emulated';
+        $this->supported['indexes'] = true;
+        $this->supported['affected_rows'] = true;
+        $this->supported['transactions'] = false;
+        $this->supported['savepoints'] = false;
+        $this->supported['summary_functions'] = true;
+        $this->supported['order_by_text'] = true;
+        $this->supported['current_id'] = 'emulated';
+        $this->supported['limit_queries'] = true;
+        $this->supported['LOBs'] = true;
+        $this->supported['replace'] = true;
+        $this->supported['sub_selects'] = 'emulated';
+        $this->supported['auto_increment'] = true;
+        $this->supported['primary_key'] = true;
+        $this->supported['result_introspection'] = true;
+        $this->supported['prepared_statements'] = 'emulated';
+        $this->supported['identifier_quoting'] = true;
+        $this->supported['pattern_escaping'] = true;
+        $this->supported['new_link'] = true;
+
+        $this->options['default_table_type'] = '';
+    }
+
+    // }}}
+    // {{{ errorInfo()
+
+    /**
+     * This method is used to collect information about an error
+     *
+     * @param integer $error
+     * @return array
+     * @access public
+     */
+    function errorInfo($error = null)
+    {
+        if ($this->connection) {
+            $native_code = @mysql_errno($this->connection);
+            $native_msg  = @mysql_error($this->connection);
+        } else {
+            $native_code = @mysql_errno();
+            $native_msg  = @mysql_error();
+        }
+        if (is_null($error)) {
+            static $ecode_map;
+            if (empty($ecode_map)) {
+                $ecode_map = array(
+                    1004 => MDB2_ERROR_CANNOT_CREATE,
+                    1005 => MDB2_ERROR_CANNOT_CREATE,
+                    1006 => MDB2_ERROR_CANNOT_CREATE,
+                    1007 => MDB2_ERROR_ALREADY_EXISTS,
+                    1008 => MDB2_ERROR_CANNOT_DROP,
+                    1022 => MDB2_ERROR_ALREADY_EXISTS,
+                    1044 => MDB2_ERROR_ACCESS_VIOLATION,
+                    1046 => MDB2_ERROR_NODBSELECTED,
+                    1048 => MDB2_ERROR_CONSTRAINT,
+                    1049 => MDB2_ERROR_NOSUCHDB,
+                    1050 => MDB2_ERROR_ALREADY_EXISTS,
+                    1051 => MDB2_ERROR_NOSUCHTABLE,
+                    1054 => MDB2_ERROR_NOSUCHFIELD,
+                    1061 => MDB2_ERROR_ALREADY_EXISTS,
+                    1062 => MDB2_ERROR_ALREADY_EXISTS,
+                    1064 => MDB2_ERROR_SYNTAX,
+                    1091 => MDB2_ERROR_NOT_FOUND,
+                    1100 => MDB2_ERROR_NOT_LOCKED,
+                    1136 => MDB2_ERROR_VALUE_COUNT_ON_ROW,
+                    1142 => MDB2_ERROR_ACCESS_VIOLATION,
+                    1146 => MDB2_ERROR_NOSUCHTABLE,
+                    1216 => MDB2_ERROR_CONSTRAINT,
+                    1217 => MDB2_ERROR_CONSTRAINT,
+                    1356 => MDB2_ERROR_DIVZERO,
+                    1451 => MDB2_ERROR_CONSTRAINT,
+                    1452 => MDB2_ERROR_CONSTRAINT,
+                );
+            }
+            if ($this->options['portability'] & MDB2_PORTABILITY_ERRORS) {
+                $ecode_map[1022] = MDB2_ERROR_CONSTRAINT;
+                $ecode_map[1048] = MDB2_ERROR_CONSTRAINT_NOT_NULL;
+                $ecode_map[1062] = MDB2_ERROR_CONSTRAINT;
+            } else {
+                // Doing this in case mode changes during runtime.
+                $ecode_map[1022] = MDB2_ERROR_ALREADY_EXISTS;
+                $ecode_map[1048] = MDB2_ERROR_CONSTRAINT;
+                $ecode_map[1062] = MDB2_ERROR_ALREADY_EXISTS;
+            }
+            if (isset($ecode_map[$native_code])) {
+                $error = $ecode_map[$native_code];
+            }
+        }
+        return array($error, $native_code, $native_msg);
+    }
+
+    // }}}
+    // {{{ escape()
+
+    /**
+     * Quotes a string so it can be safely used in a query. It will quote
+     * the text so it can safely be used within a query.
+     *
+     * @param   string  the input string to quote
+     * @param   bool    escape wildcards
+     *
+     * @return  string  quoted string
+     *
+     * @access  public
+     */
+    function escape($text, $escape_wildcards = false)
+    {
+        if ($escape_wildcards) {
+            $text = $this->escapePattern($text);
+        }
+        $connection = $this->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+        $text = @mysql_real_escape_string($text, $connection);
+        return $text;
+    }
+
+    // }}}
+    // {{{
+
+    /**
+     * Start a transaction or set a savepoint.
+     *
+     * @param   string  name of a savepoint to set
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function beginTransaction($savepoint = null)
+    {
+        $this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
+        $this->_getServerCapabilities();
+        if (!is_null($savepoint)) {
+            if (!$this->supports('savepoints')) {
+                return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                    'savepoints are not supported', __FUNCTION__);
+            }
+            if (!$this->in_transaction) {
+                return $this->raiseError(MDB2_ERROR_INVALID, null, null,
+                    'savepoint cannot be released when changes are auto committed', __FUNCTION__);
+            }
+            $query = 'SAVEPOINT '.$savepoint;
+            return $this->_doQuery($query, true);
+        } elseif ($this->in_transaction) {
+            return MDB2_OK;  //nothing to do
+        }
+        if (!$this->destructor_registered && $this->opened_persistent) {
+            $this->destructor_registered = true;
+            register_shutdown_function('MDB2_closeOpenTransactions');
+        }
+        $query = $this->start_transaction ? 'START TRANSACTION' : 'SET AUTOCOMMIT = 1';
+        $result =& $this->_doQuery($query, true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        $this->in_transaction = true;
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ commit()
+
+    /**
+     * Commit the database changes done during a transaction that is in
+     * progress or release a savepoint. This function may only be called when
+     * auto-committing is disabled, otherwise it will fail. Therefore, a new
+     * transaction is implicitly started after committing the pending changes.
+     *
+     * @param   string  name of a savepoint to release
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function commit($savepoint = null)
+    {
+        $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
+        if (!$this->in_transaction) {
+            return $this->raiseError(MDB2_ERROR_INVALID, null, null,
+                'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__);
+        }
+        if (!is_null($savepoint)) {
+            if (!$this->supports('savepoints')) {
+                return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                    'savepoints are not supported', __FUNCTION__);
+            }
+            $server_info = $this->getServerVersion();
+            if (version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '5.0.3', '<')) {
+                return MDB2_OK;
+            }
+            $query = 'RELEASE SAVEPOINT '.$savepoint;
+            return $this->_doQuery($query, true);
+        }
+
+        if (!$this->supports('transactions')) {
+            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'transactions are not supported', __FUNCTION__);
+        }
+
+        $result =& $this->_doQuery('COMMIT', true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        if (!$this->start_transaction) {
+            $query = 'SET AUTOCOMMIT = 0';
+            $result =& $this->_doQuery($query, true);
+            if (PEAR::isError($result)) {
+                return $result;
+            }
+        }
+        $this->in_transaction = false;
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ rollback()
+
+    /**
+     * Cancel any database changes done during a transaction or since a specific
+     * savepoint that is in progress. This function may only be called when
+     * auto-committing is disabled, otherwise it will fail. Therefore, a new
+     * transaction is implicitly started after canceling the pending changes.
+     *
+     * @param   string  name of a savepoint to rollback to
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function rollback($savepoint = null)
+    {
+        $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
+        if (!$this->in_transaction) {
+            return $this->raiseError(MDB2_ERROR_INVALID, null, null,
+                'rollback cannot be done changes are auto committed', __FUNCTION__);
+        }
+        if (!is_null($savepoint)) {
+            if (!$this->supports('savepoints')) {
+                return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                    'savepoints are not supported', __FUNCTION__);
+            }
+            $query = 'ROLLBACK TO SAVEPOINT '.$savepoint;
+            return $this->_doQuery($query, true);
+        }
+
+        $query = 'ROLLBACK';
+        $result =& $this->_doQuery($query, true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        if (!$this->start_transaction) {
+            $query = 'SET AUTOCOMMIT = 0';
+            $result =& $this->_doQuery($query, true);
+            if (PEAR::isError($result)) {
+                return $result;
+            }
+        }
+        $this->in_transaction = false;
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function setTransactionIsolation()
+
+    /**
+     * Set the transacton isolation level.
+     *
+     * @param   string  standard isolation level
+     *                  READ UNCOMMITTED (allows dirty reads)
+     *                  READ COMMITTED (prevents dirty reads)
+     *                  REPEATABLE READ (prevents nonrepeatable reads)
+     *                  SERIALIZABLE (prevents phantom reads)
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     * @since   2.1.1
+     */
+    function setTransactionIsolation($isolation)
+    {
+        $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true));
+        if (!$this->supports('transactions')) {
+            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'transactions are not supported', __FUNCTION__);
+        }
+        switch ($isolation) {
+        case 'READ UNCOMMITTED':
+        case 'READ COMMITTED':
+        case 'REPEATABLE READ':
+        case 'SERIALIZABLE':
+            break;
+        default:
+            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'isolation level is not supported: '.$isolation, __FUNCTION__);
+        }
+
+        $query = "SET SESSION TRANSACTION ISOLATION LEVEL $isolation";
+        return $this->_doQuery($query, true);
+    }
+
+    // }}}
+    // {{{ connect()
+
+    /**
+     * Connect to the database
+     *
+     * @return true on success, MDB2 Error Object on failure
+     */
+    function connect()
+    {
+        if (is_resource($this->connection)) {
+            if (count(array_diff($this->connected_dsn, $this->dsn)) == 0
+                && $this->opened_persistent == $this->options['persistent']
+                && $this->connected_database_name == $this->database_name
+            ) {
+                return MDB2_OK;
+            }
+            $this->disconnect(false);
+        }
+
+        if (!PEAR::loadExtension($this->phptype)) {
+            return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
+        }
+
+        $params = array();
+        if ($this->dsn['protocol'] && $this->dsn['protocol'] == 'unix') {
+            $params[0] = ':' . $this->dsn['socket'];
+        } else {
+            $params[0] = $this->dsn['hostspec'] ? $this->dsn['hostspec']
+                         : 'localhost';
+            if ($this->dsn['port']) {
+                $params[0].= ':' . $this->dsn['port'];
+            }
+        }
+        $params[] = $this->dsn['username'] ? $this->dsn['username'] : null;
+        $params[] = $this->dsn['password'] ? $this->dsn['password'] : null;
+        if (!$this->options['persistent']) {
+            if (isset($this->dsn['new_link'])
+                && ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true)
+            ) {
+                $params[] = true;
+            } else {
+                $params[] = false;
+            }
+        }
+        if (version_compare(phpversion(), '4.3.0', '>=')) {
+            $params[] = isset($this->dsn['client_flags'])
+                ? $this->dsn['client_flags'] : null;
+        }
+        $connect_function = $this->options['persistent'] ? 'mysql_pconnect' : 'mysql_connect';
+
+        $connection = @call_user_func_array($connect_function, $params);
+        if (!$connection) {
+            if (($err = @mysql_error()) != '') {
+                return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
+                    $err, __FUNCTION__);
+            } else {
+                return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
+                    'unable to establish a connection', __FUNCTION__);
+            }
+        }
+
+        if (!empty($this->dsn['charset'])) {
+            $result = $this->setCharset($this->dsn['charset'], $connection);
+            if (PEAR::isError($result)) {
+                return $result;
+            }
+        }
+
+        $this->connection = $connection;
+        $this->connected_dsn = $this->dsn;
+        $this->connected_database_name = '';
+        $this->opened_persistent = $this->options['persistent'];
+        $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype;
+
+        if ($this->database_name) {
+            if ($this->database_name != $this->connected_database_name) {
+                if (!@mysql_select_db($this->database_name, $connection)) {
+                    $err = $this->raiseError(null, null, null,
+                        'Could not select the database: '.$this->database_name, __FUNCTION__);
+                    return $err;
+                }
+                $this->connected_database_name = $this->database_name;
+            }
+        }
+
+        $this->supported['transactions'] = $this->options['use_transactions'];
+        if ($this->options['default_table_type']) {
+            switch (strtoupper($this->options['default_table_type'])) {
+            case 'BLACKHOLE':
+            case 'MEMORY':
+            case 'ARCHIVE':
+            case 'CSV':
+            case 'HEAP':
+            case 'ISAM':
+            case 'MERGE':
+            case 'MRG_ISAM':
+            case 'ISAM':
+            case 'MRG_MYISAM':
+            case 'MYISAM':
+                $this->supported['transactions'] = false;
+                $this->warnings[] = $this->options['default_table_type'] .
+                    ' is not a supported default table type';
+                break;
+            }
+        }
+        
+        $this->_getServerCapabilities();
+
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ setCharset()
+
+    /**
+     * Set the charset on the current connection
+     *
+     * @param string    charset
+     * @param resource  connection handle
+     *
+     * @return true on success, MDB2 Error Object on failure
+     */
+    function setCharset($charset, $connection = null)
+    {
+        if (is_null($connection)) {
+            $connection = $this->getConnection();
+            if (PEAR::isError($connection)) {
+                return $connection;
+            }
+        }
+        $query = "SET NAMES '".mysql_real_escape_string($charset, $connection)."'";
+        return $this->_doQuery($query, true, $connection);
+    }
+
+    // }}}
+    // {{{ disconnect()
+
+    /**
+     * Log out and disconnect from the database.
+     *
+     * @param  boolean $force if the disconnect should be forced even if the
+     *                        connection is opened persistently
+     * @return mixed true on success, false if not connected and error
+     *                object on error
+     * @access public
+     */
+    function disconnect($force = true)
+    {
+        if (is_resource($this->connection)) {
+            if ($this->in_transaction) {
+                $dsn = $this->dsn;
+                $database_name = $this->database_name;
+                $persistent = $this->options['persistent'];
+                $this->dsn = $this->connected_dsn;
+                $this->database_name = $this->connected_database_name;
+                $this->options['persistent'] = $this->opened_persistent;
+                $this->rollback();
+                $this->dsn = $dsn;
+                $this->database_name = $database_name;
+                $this->options['persistent'] = $persistent;
+            }
+
+            if (!$this->opened_persistent || $force) {
+                @mysql_close($this->connection);
+            }
+        }
+        return parent::disconnect($force);
+    }
+
+    // }}}
+    // {{{ _doQuery()
+
+    /**
+     * Execute a query
+     * @param string $query  query
+     * @param boolean $is_manip  if the query is a manipulation query
+     * @param resource $connection
+     * @param string $database_name
+     * @return result or error object
+     * @access protected
+     */
+    function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null)
+    {
+        $this->last_query = $query;
+        $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre'));
+        if ($result) {
+            if (PEAR::isError($result)) {
+                return $result;
+            }
+            $query = $result;
+        }
+        if ($this->options['disable_query']) {
+            $result = $is_manip ? 0 : null;
+            return $result;
+        }
+
+        if (is_null($connection)) {
+            $connection = $this->getConnection();
+            if (PEAR::isError($connection)) {
+                return $connection;
+            }
+        }
+        if (is_null($database_name)) {
+            $database_name = $this->database_name;
+        }
+
+        if ($database_name) {
+            if ($database_name != $this->connected_database_name) {
+                if (!@mysql_select_db($database_name, $connection)) {
+                    $err = $this->raiseError(null, null, null,
+                        'Could not select the database: '.$database_name, __FUNCTION__);
+                    return $err;
+                }
+                $this->connected_database_name = $database_name;
+            }
+        }
+
+        $function = $this->options['result_buffering']
+            ? 'mysql_query' : 'mysql_unbuffered_query';
+        $result = @$function($query, $connection);
+        if (!$result) {
+            $err =& $this->raiseError(null, null, null,
+                'Could not execute statement', __FUNCTION__);
+            return $err;
+        }
+
+        $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'post', 'result' => $result));
+        return $result;
+    }
+
+    // }}}
+    // {{{ _affectedRows()
+
+    /**
+     * Returns the number of rows affected
+     *
+     * @param resource $result
+     * @param resource $connection
+     * @return mixed MDB2 Error Object or the number of rows affected
+     * @access private
+     */
+    function _affectedRows($connection, $result = null)
+    {
+        if (is_null($connection)) {
+            $connection = $this->getConnection();
+            if (PEAR::isError($connection)) {
+                return $connection;
+            }
+        }
+        return @mysql_affected_rows($connection);
+    }
+
+    // }}}
+    // {{{ _modifyQuery()
+
+    /**
+     * Changes a query string for various DBMS specific reasons
+     *
+     * @param string $query  query to modify
+     * @param boolean $is_manip  if it is a DML query
+     * @param integer $limit  limit the number of rows
+     * @param integer $offset  start reading from given offset
+     * @return string modified query
+     * @access protected
+     */
+    function _modifyQuery($query, $is_manip, $limit, $offset)
+    {
+        if ($this->options['portability'] & MDB2_PORTABILITY_DELETE_COUNT) {
+            // "DELETE FROM table" gives 0 affected rows in MySQL.
+            // This little hack lets you know how many rows were deleted.
+            if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
+                $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
+                                      'DELETE FROM \1 WHERE 1=1', $query);
+            }
+        }
+        if ($limit > 0
+            && !preg_match('/LIMIT\s*\d(?:\s*(?:,|OFFSET)\s*\d+)?(?:[^\)]*)?$/i', $query)
+        ) {
+            $query = rtrim($query);
+            if (substr($query, -1) == ';') {
+                $query = substr($query, 0, -1);
+            }
+
+            // LIMIT doesn't always come last in the query
+            // @see http://dev.mysql.com/doc/refman/5.0/en/select.html
+            $after = '';
+            if (preg_match('/(\s+INTO\s+(?:OUT|DUMP)FILE\s.*)$/ims', $query, $matches)) {
+                $after = $matches[0];
+                $query = preg_replace('/(\s+INTO\s+(?:OUT|DUMP)FILE\s.*)$/ims', '', $query);
+            } elseif (preg_match('/(\s+FOR\s+UPDATE\s*)$/i', $query, $matches)) {
+               $after = $matches[0];
+               $query = preg_replace('/(\s+FOR\s+UPDATE\s*)$/im', '', $query);
+            } elseif (preg_match('/(\s+LOCK\s+IN\s+SHARE\s+MODE\s*)$/im', $query, $matches)) {
+               $after = $matches[0];
+               $query = preg_replace('/(\s+LOCK\s+IN\s+SHARE\s+MODE\s*)$/im', '', $query);
+            }
+
+            if ($is_manip) {
+                return $query . " LIMIT $limit" . $after;
+            } else {
+                return $query . " LIMIT $offset, $limit" . $after;
+            }
+        }
+        return $query;
+    }
+
+    // }}}
+    // {{{ getServerVersion()
+
+    /**
+     * return version information about the server
+     *
+     * @param bool   $native  determines if the raw version string should be returned
+     * @return mixed array/string with version information or MDB2 error object
+     * @access public
+     */
+    function getServerVersion($native = false)
+    {
+        $connection = $this->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+        if ($this->connected_server_info) {
+            $server_info = $this->connected_server_info;
+        } else {
+            $server_info = @mysql_get_server_info($connection);
+        }
+        if (!$server_info) {
+            return $this->raiseError(null, null, null,
+                'Could not get server information', __FUNCTION__);
+        }
+        // cache server_info
+        $this->connected_server_info = $server_info;
+        if (!$native) {
+            $tmp = explode('.', $server_info, 3);
+            if (isset($tmp[2]) && strpos($tmp[2], '-')) {
+                $tmp2 = explode('-', @$tmp[2], 2);
+            } else {
+                $tmp2[0] = isset($tmp[2]) ? $tmp[2] : null;
+                $tmp2[1] = null;
+            }
+            $server_info = array(
+                'major' => isset($tmp[0]) ? $tmp[0] : null,
+                'minor' => isset($tmp[1]) ? $tmp[1] : null,
+                'patch' => $tmp2[0],
+                'extra' => $tmp2[1],
+                'native' => $server_info,
+            );
+        }
+        return $server_info;
+    }
+
+    // }}}
+    // {{{ _getServerCapabilities()
+
+    /**
+     * Fetch some information about the server capabilities
+     * (transactions, subselects, prepared statements, etc).
+     *
+     * @access private
+     */
+    function _getServerCapabilities()
+    {
+        static $already_checked = false;
+        if (!$already_checked) {
+            $already_checked = true;
+
+            //set defaults
+            $this->supported['sub_selects'] = 'emulated';
+            $this->supported['prepared_statements'] = 'emulated';
+            $this->start_transaction = false;
+            $this->varchar_max_length = 255;
+            
+            $server_info = $this->getServerVersion();
+            if (is_array($server_info)) {
+                if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.1.0', '<')) {
+                    $this->supported['sub_selects'] = true;
+                    $this->supported['prepared_statements'] = true;
+                }
+
+                if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.0.14', '<')
+                    || !version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.1.1', '<')
+                ) {
+                    $this->supported['savepoints'] = true;
+                }
+
+                if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.0.11', '<')) {
+                    $this->start_transaction = true;
+                }
+
+                if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '5.0.3', '<')) {
+                    $this->varchar_max_length = 65532;
+                }
+            }
+        }
+    }
+
+    // }}}
+    // {{{ function _skipUserDefinedVariable($query, $position)
+
+    /**
+     * Utility method, used by prepare() to avoid misinterpreting MySQL user 
+     * defined variables (SELECT @x:=5) for placeholders.
+     * Check if the placeholder is a false positive, i.e. if it is an user defined
+     * variable instead. If so, skip it and advance the position, otherwise
+     * return the current position, which is valid
+     *
+     * @param string $query
+     * @param integer $position current string cursor position
+     * @return integer $new_position
+     * @access protected
+     */
+    function _skipUserDefinedVariable($query, $position)
+    {
+        $found = strpos(strrev(substr($query, 0, $position)), '@');
+        if ($found === false) {
+            return $position;
+        }
+        $pos = strlen($query) - strlen(substr($query, $position)) - $found - 1;
+        $substring = substr($query, $pos, $position - $pos + 2);
+        if (preg_match('/^@\w+:=$/', $substring)) {
+            return $position + 1; //found an user defined variable: skip it
+        }
+        return $position;
+    }
+
+    // }}}
+    // {{{ prepare()
+
+    /**
+     * Prepares a query for multiple execution with execute().
+     * With some database backends, this is emulated.
+     * prepare() requires a generic query as string like
+     * 'INSERT INTO numbers VALUES(?,?)' or
+     * 'INSERT INTO numbers VALUES(:foo,:bar)'.
+     * The ? and :[a-zA-Z] and  are placeholders which can be set using
+     * bindParam() and the query can be send off using the execute() method.
+     *
+     * @param string $query the query to prepare
+     * @param mixed   $types  array that contains the types of the placeholders
+     * @param mixed   $result_types  array that contains the types of the columns in
+     *                        the result set or MDB2_PREPARE_RESULT, if set to
+     *                        MDB2_PREPARE_MANIP the query is handled as a manipulation query
+     * @param mixed   $lobs   key (field) value (parameter) pair for all lob placeholders
+     * @return mixed resource handle for the prepared query on success, a MDB2
+     *        error on failure
+     * @access public
+     * @see bindParam, execute
+     */
+    function &prepare($query, $types = null, $result_types = null, $lobs = array())
+    {
+        if ($this->options['emulate_prepared']
+            || $this->supported['prepared_statements'] !== true
+        ) {
+            $obj =& parent::prepare($query, $types, $result_types, $lobs);
+            return $obj;
+        }
+        $is_manip = ($result_types === MDB2_PREPARE_MANIP);
+        $offset = $this->offset;
+        $limit = $this->limit;
+        $this->offset = $this->limit = 0;
+        $query = $this->_modifyQuery($query, $is_manip, $limit, $offset);
+        $result = $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'pre'));
+        if ($result) {
+            if (PEAR::isError($result)) {
+                return $result;
+            }
+            $query = $result;
+        }
+        $placeholder_type_guess = $placeholder_type = null;
+        $question = '?';
+        $colon = ':';
+        $positions = array();
+        $position = 0;
+        while ($position < strlen($query)) {
+            $q_position = strpos($query, $question, $position);
+            $c_position = strpos($query, $colon, $position);
+            if ($q_position && $c_position) {
+                $p_position = min($q_position, $c_position);
+            } elseif ($q_position) {
+                $p_position = $q_position;
+            } elseif ($c_position) {
+                $p_position = $c_position;
+            } else {
+                break;
+            }
+            if (is_null($placeholder_type)) {
+                $placeholder_type_guess = $query[$p_position];
+            }
+            
+            $new_pos = $this->_skipDelimitedStrings($query, $position, $p_position);
+            if (PEAR::isError($new_pos)) {
+                return $new_pos;
+            }
+            if ($new_pos != $position) {
+                $position = $new_pos;
+                continue; //evaluate again starting from the new position
+            }
+            
+            if ($query[$position] == $placeholder_type_guess) {
+                if (is_null($placeholder_type)) {
+                    $placeholder_type = $query[$p_position];
+                    $question = $colon = $placeholder_type;
+                }
+                if ($placeholder_type == ':') {
+                    //make sure this is not part of an user defined variable
+                    $new_pos = $this->_skipUserDefinedVariable($query, $position);
+                    if ($new_pos != $position) {
+                        $position = $new_pos;
+                        continue; //evaluate again starting from the new position
+                    }
+                    $parameter = preg_replace('/^.{'.($position+1).'}([a-z0-9_]+).*$/si', '\\1', $query);
+                    if ($parameter === '') {
+                        $err =& $this->raiseError(MDB2_ERROR_SYNTAX, null, null,
+                            'named parameter with an empty name', __FUNCTION__);
+                        return $err;
+                    }
+                    $positions[$p_position] = $parameter;
+                    $query = substr_replace($query, '?', $position, strlen($parameter)+1);
+                } else {
+                    $positions[$p_position] = count($positions);
+                }
+                $position = $p_position + 1;
+            } else {
+                $position = $p_position;
+            }
+        }
+        $connection = $this->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+        $statement_name = sprintf($this->options['statement_format'], $this->phptype, md5(time() + rand()));
+        $query = "PREPARE $statement_name FROM ".$this->quote($query, 'text');
+        $statement =& $this->_doQuery($query, true, $connection);
+        if (PEAR::isError($statement)) {
+            return $statement;
+        }
+
+        $class_name = 'MDB2_Statement_'.$this->phptype;
+        $obj =& new $class_name($this, $statement_name, $positions, $query, $types, $result_types, $is_manip, $limit, $offset);
+        $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'post', 'result' => $obj));
+        return $obj;
+    }
+
+    // }}}
+    // {{{ replace()
+
+    /**
+     * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
+     * query, except that if there is already a row in the table with the same
+     * key field values, the REPLACE query just updates its values instead of
+     * inserting a new row.
+     *
+     * The REPLACE type of query does not make part of the SQL standards. Since
+     * practically only MySQL implements it natively, this type of query is
+     * emulated through this method for other DBMS using standard types of
+     * queries inside a transaction to assure the atomicity of the operation.
+     *
+     * @access public
+     *
+     * @param string $table name of the table on which the REPLACE query will
+     *  be executed.
+     * @param array $fields associative array that describes the fields and the
+     *  values that will be inserted or updated in the specified table. The
+     *  indexes of the array are the names of all the fields of the table. The
+     *  values of the array are also associative arrays that describe the
+     *  values and other properties of the table fields.
+     *
+     *  Here follows a list of field properties that need to be specified:
+     *
+     *    value:
+     *          Value to be assigned to the specified field. This value may be
+     *          of specified in database independent type format as this
+     *          function can perform the necessary datatype conversions.
+     *
+     *    Default:
+     *          this property is required unless the Null property
+     *          is set to 1.
+     *
+     *    type
+     *          Name of the type of the field. Currently, all types Metabase
+     *          are supported except for clob and blob.
+     *
+     *    Default: no type conversion
+     *
+     *    null
+     *          Boolean property that indicates that the value for this field
+     *          should be set to null.
+     *
+     *          The default value for fields missing in INSERT queries may be
+     *          specified the definition of a table. Often, the default value
+     *          is already null, but since the REPLACE may be emulated using
+     *          an UPDATE query, make sure that all fields of the table are
+     *          listed in this function argument array.
+     *
+     *    Default: 0
+     *
+     *    key
+     *          Boolean property that indicates that this field should be
+     *          handled as a primary key or at least as part of the compound
+     *          unique index of the table that will determine the row that will
+     *          updated if it exists or inserted a new row otherwise.
+     *
+     *          This function will fail if no key field is specified or if the
+     *          value of a key field is set to null because fields that are
+     *          part of unique index they may not be null.
+     *
+     *    Default: 0
+     *
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     */
+    function replace($table, $fields)
+    {
+        $count = count($fields);
+        $query = $values = '';
+        $keys = $colnum = 0;
+        for (reset($fields); $colnum < $count; next($fields), $colnum++) {
+            $name = key($fields);
+            if ($colnum > 0) {
+                $query .= ',';
+                $values.= ',';
+            }
+            $query.= $name;
+            if (isset($fields[$name]['null']) && $fields[$name]['null']) {
+                $value = 'NULL';
+            } else {
+                $type = isset($fields[$name]['type']) ? $fields[$name]['type'] : null;
+                $value = $this->quote($fields[$name]['value'], $type);
+            }
+            $values.= $value;
+            if (isset($fields[$name]['key']) && $fields[$name]['key']) {
+                if ($value === 'NULL') {
+                    return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null,
+                        'key value '.$name.' may not be NULL', __FUNCTION__);
+                }
+                $keys++;
+            }
+        }
+        if ($keys == 0) {
+            return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null,
+                'not specified which fields are keys', __FUNCTION__);
+        }
+
+        $connection = $this->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+
+        $query = "REPLACE INTO $table ($query) VALUES ($values)";
+        $result =& $this->_doQuery($query, true, $connection);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        return $this->_affectedRows($connection, $result);
+    }
+
+    // }}}
+    // {{{ nextID()
+
+    /**
+     * Returns the next free id of a sequence
+     *
+     * @param string $seq_name name of the sequence
+     * @param boolean $ondemand when true the sequence is
+     *                          automatic created, if it
+     *                          not exists
+     *
+     * @return mixed MDB2 Error Object or id
+     * @access public
+     */
+    function nextID($seq_name, $ondemand = true)
+    {
+        $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
+        $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true);
+        $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)";
+        $this->expectError(MDB2_ERROR_NOSUCHTABLE);
+        $result =& $this->_doQuery($query, true);
+        $this->popExpect();
+        if (PEAR::isError($result)) {
+            if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) {
+                $this->loadModule('Manager', null, true);
+                $result = $this->manager->createSequence($seq_name);
+                if (PEAR::isError($result)) {
+                    return $this->raiseError($result, null, null,
+                        'on demand sequence '.$seq_name.' could not be created', __FUNCTION__);
+                } else {
+                    return $this->nextID($seq_name, false);
+                }
+            }
+            return $result;
+        }
+        $value = $this->lastInsertID();
+        if (is_numeric($value)) {
+            $query = "DELETE FROM $sequence_name WHERE $seqcol_name < $value";
+            $result =& $this->_doQuery($query, true);
+            if (PEAR::isError($result)) {
+                $this->warnings[] = 'nextID: could not delete previous sequence table values from '.$seq_name;
+            }
+        }
+        return $value;
+    }
+
+    // }}}
+    // {{{ lastInsertID()
+
+    /**
+     * Returns the autoincrement ID if supported or $id or fetches the current
+     * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
+     *
+     * @param string $table name of the table into which a new row was inserted
+     * @param string $field name of the field into which a new row was inserted
+     * @return mixed MDB2 Error Object or id
+     * @access public
+     */
+    function lastInsertID($table = null, $field = null)
+    {
+        // not using mysql_insert_id() due to http://pear.php.net/bugs/bug.php?id=8051
+        return $this->queryOne('SELECT LAST_INSERT_ID()', 'integer');
+    }
+
+    // }}}
+    // {{{ currID()
+
+    /**
+     * Returns the current id of a sequence
+     *
+     * @param string $seq_name name of the sequence
+     * @return mixed MDB2 Error Object or id
+     * @access public
+     */
+    function currID($seq_name)
+    {
+        $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
+        $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true);
+        $query = "SELECT MAX($seqcol_name) FROM $sequence_name";
+        return $this->queryOne($query, 'integer');
+    }
+}
+
+/**
+ * MDB2 MySQL result driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Result_mysql extends MDB2_Result_Common
+{
+    // }}}
+    // {{{ fetchRow()
+
+    /**
+     * Fetch a row and insert the data into an existing array.
+     *
+     * @param int       $fetchmode  how the array data should be indexed
+     * @param int    $rownum    number of the row where the data can be found
+     * @return int data array on success, a MDB2 error on failure
+     * @access public
+     */
+    function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)
+    {
+        if (!is_null($rownum)) {
+            $seek = $this->seek($rownum);
+            if (PEAR::isError($seek)) {
+                return $seek;
+            }
+        }
+        if ($fetchmode == MDB2_FETCHMODE_DEFAULT) {
+            $fetchmode = $this->db->fetchmode;
+        }
+        if ($fetchmode & MDB2_FETCHMODE_ASSOC) {
+            $row = @mysql_fetch_assoc($this->result);
+            if (is_array($row)
+                && $this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE
+            ) {
+                $row = array_change_key_case($row, $this->db->options['field_case']);
+            }
+        } else {
+           $row = @mysql_fetch_row($this->result);
+        }
+
+        if (!$row) {
+            if ($this->result === false) {
+                $err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                    'resultset has already been freed', __FUNCTION__);
+                return $err;
+            }
+            $null = null;
+            return $null;
+        }
+        $mode = $this->db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL;
+        if ($mode) {
+            $this->db->_fixResultArrayValues($row, $mode);
+        }
+        if (!empty($this->types)) {
+            $row = $this->db->datatype->convertResultRow($this->types, $row, false);
+        }
+        if (!empty($this->values)) {
+            $this->_assignBindColumns($row);
+        }
+        if ($fetchmode === MDB2_FETCHMODE_OBJECT) {
+            $object_class = $this->db->options['fetch_class'];
+            if ($object_class == 'stdClass') {
+                $row = (object) $row;
+            } else {
+                $row = &new $object_class($row);
+            }
+        }
+        ++$this->rownum;
+        return $row;
+    }
+
+    // }}}
+    // {{{ _getColumnNames()
+
+    /**
+     * Retrieve the names of columns returned by the DBMS in a query result.
+     *
+     * @return  mixed   Array variable that holds the names of columns as keys
+     *                  or an MDB2 error on failure.
+     *                  Some DBMS may not return any columns when the result set
+     *                  does not contain any rows.
+     * @access private
+     */
+    function _getColumnNames()
+    {
+        $columns = array();
+        $numcols = $this->numCols();
+        if (PEAR::isError($numcols)) {
+            return $numcols;
+        }
+        for ($column = 0; $column < $numcols; $column++) {
+            $column_name = @mysql_field_name($this->result, $column);
+            $columns[$column_name] = $column;
+        }
+        if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $columns = array_change_key_case($columns, $this->db->options['field_case']);
+        }
+        return $columns;
+    }
+
+    // }}}
+    // {{{ numCols()
+
+    /**
+     * Count the number of columns returned by the DBMS in a query result.
+     *
+     * @return mixed integer value with the number of columns, a MDB2 error
+     *                       on failure
+     * @access public
+     */
+    function numCols()
+    {
+        $cols = @mysql_num_fields($this->result);
+        if (is_null($cols)) {
+            if ($this->result === false) {
+                return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                    'resultset has already been freed', __FUNCTION__);
+            } elseif (is_null($this->result)) {
+                return count($this->types);
+            }
+            return $this->db->raiseError(null, null, null,
+                'Could not get column count', __FUNCTION__);
+        }
+        return $cols;
+    }
+
+    // }}}
+    // {{{ free()
+
+    /**
+     * Free the internal resources associated with result.
+     *
+     * @return boolean true on success, false if result is invalid
+     * @access public
+     */
+    function free()
+    {
+        if (is_resource($this->result) && $this->db->connection) {
+            $free = @mysql_free_result($this->result);
+            if ($free === false) {
+                return $this->db->raiseError(null, null, null,
+                    'Could not free result', __FUNCTION__);
+            }
+        }
+        $this->result = false;
+        return MDB2_OK;
+    }
+}
+
+/**
+ * MDB2 MySQL buffered result driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_BufferedResult_mysql extends MDB2_Result_mysql
+{
+    // }}}
+    // {{{ seek()
+
+    /**
+     * Seek to a specific row in a result set
+     *
+     * @param int    $rownum    number of the row where the data can be found
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function seek($rownum = 0)
+    {
+        if ($this->rownum != ($rownum - 1) && !@mysql_data_seek($this->result, $rownum)) {
+            if ($this->result === false) {
+                return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                    'resultset has already been freed', __FUNCTION__);
+            } elseif (is_null($this->result)) {
+                return MDB2_OK;
+            }
+            return $this->db->raiseError(MDB2_ERROR_INVALID, null, null,
+                'tried to seek to an invalid row number ('.$rownum.')', __FUNCTION__);
+        }
+        $this->rownum = $rownum - 1;
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ valid()
+
+    /**
+     * Check if the end of the result set has been reached
+     *
+     * @return mixed true or false on sucess, a MDB2 error on failure
+     * @access public
+     */
+    function valid()
+    {
+        $numrows = $this->numRows();
+        if (PEAR::isError($numrows)) {
+            return $numrows;
+        }
+        return $this->rownum < ($numrows - 1);
+    }
+
+    // }}}
+    // {{{ numRows()
+
+    /**
+     * Returns the number of rows in a result object
+     *
+     * @return mixed MDB2 Error Object or the number of rows
+     * @access public
+     */
+    function numRows()
+    {
+        $rows = @mysql_num_rows($this->result);
+        if (is_null($rows)) {
+            if ($this->result === false) {
+                return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                    'resultset has already been freed', __FUNCTION__);
+            } elseif (is_null($this->result)) {
+                return 0;
+            }
+            return $this->db->raiseError(null, null, null,
+                'Could not get row count', __FUNCTION__);
+        }
+        return $rows;
+    }
+}
+
+/**
+ * MDB2 MySQL statement driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Statement_mysql extends MDB2_Statement_Common
+{
+    // {{{ _execute()
+
+    /**
+     * Execute a prepared query statement helper method.
+     *
+     * @param mixed $result_class string which specifies which result class to use
+     * @param mixed $result_wrap_class string which specifies which class to wrap results in
+     * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
+     * @access private
+     */
+    function &_execute($result_class = true, $result_wrap_class = false)
+    {
+        if (is_null($this->statement)) {
+            $result =& parent::_execute($result_class, $result_wrap_class);
+            return $result;
+        }
+        $this->db->last_query = $this->query;
+        $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'pre', 'parameters' => $this->values));
+        if ($this->db->getOption('disable_query')) {
+            $result = $this->is_manip ? 0 : null;
+            return $result;
+        }
+
+        $connection = $this->db->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+
+        $query = 'EXECUTE '.$this->statement;
+        if (!empty($this->positions)) {
+            $parameters = array();
+            foreach ($this->positions as $parameter) {
+                if (!array_key_exists($parameter, $this->values)) {
+                    return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                        'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__);
+                }
+                $value = $this->values[$parameter];
+                $type = array_key_exists($parameter, $this->types) ? $this->types[$parameter] : null;
+                if (is_resource($value) || $type == 'clob' || $type == 'blob') {
+                    if (!is_resource($value) && preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) {
+                        if ($match[1] == 'file://') {
+                            $value = $match[2];
+                        }
+                        $value = @fopen($value, 'r');
+                        $close = true;
+                    }
+                    if (is_resource($value)) {
+                        $data = '';
+                        while (!@feof($value)) {
+                            $data.= @fread($value, $this->db->options['lob_buffer_length']);
+                        }
+                        if ($close) {
+                            @fclose($value);
+                        }
+                        $value = $data;
+                    }
+                }
+                $quoted = $this->db->quote($value, $type);
+                if (PEAR::isError($quoted)) {
+                    return $quoted;
+                }
+                $param_query = 'SET @'.$parameter.' = '.$quoted;
+                $result = $this->db->_doQuery($param_query, true, $connection);
+                if (PEAR::isError($result)) {
+                    return $result;
+                }
+            }
+            $query.= ' USING @'.implode(', @', array_values($this->positions));
+        }
+
+        $result = $this->db->_doQuery($query, $this->is_manip, $connection);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+
+        if ($this->is_manip) {
+            $affected_rows = $this->db->_affectedRows($connection, $result);
+            return $affected_rows;
+        }
+
+        $result =& $this->db->_wrapResult($result, $this->result_types,
+            $result_class, $result_wrap_class, $this->limit, $this->offset);
+        $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'post', 'result' => $result));
+        return $result;
+    }
+
+    // }}}
+    // {{{ free()
+
+    /**
+     * Release resources allocated for the specified prepared query.
+     *
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function free()
+    {
+        if (is_null($this->positions)) {
+            return $this->db->raiseError(MDB2_ERROR, null, null,
+                'Prepared statement has already been freed', __FUNCTION__);
+        }
+        $result = MDB2_OK;
+
+        if (!is_null($this->statement)) {
+            $connection = $this->db->getConnection();
+            if (PEAR::isError($connection)) {
+                return $connection;
+            }
+            $query = 'DEALLOCATE PREPARE '.$this->statement;
+            $result = $this->db->_doQuery($query, true, $connection);
+        }
+
+        parent::free();
+        return $result;
+    }
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/pgsql.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/pgsql.php
new file mode 100644 (file)
index 0000000..fe7876f
--- /dev/null
@@ -0,0 +1,1435 @@
+<?php
+// vim: set et ts=4 sw=4 fdm=marker:
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Paul Cooper <pgc@ucecom.com>                                 |
+// +----------------------------------------------------------------------+
+//
+// $Id: pgsql.php,v 1.173 2007/05/02 22:00:08 quipo Exp $
+
+/**
+ * MDB2 PostGreSQL driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Paul Cooper <pgc@ucecom.com>
+ */
+class MDB2_Driver_pgsql extends MDB2_Driver_Common
+{
+    // {{{ properties
+    var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => "'", 'escape_pattern' => '\\');
+
+    var $identifier_quoting = array('start' => '"', 'end' => '"', 'escape' => '"');
+    // }}}
+    // {{{ constructor
+
+    /**
+     * Constructor
+     */
+    function __construct()
+    {
+        parent::__construct();
+
+        $this->phptype = 'pgsql';
+        $this->dbsyntax = 'pgsql';
+
+        $this->supported['sequences'] = true;
+        $this->supported['indexes'] = true;
+        $this->supported['affected_rows'] = true;
+        $this->supported['summary_functions'] = true;
+        $this->supported['order_by_text'] = true;
+        $this->supported['transactions'] = true;
+        $this->supported['savepoints'] = true;
+        $this->supported['current_id'] = true;
+        $this->supported['limit_queries'] = true;
+        $this->supported['LOBs'] = true;
+        $this->supported['replace'] = 'emulated';
+        $this->supported['sub_selects'] = true;
+        $this->supported['auto_increment'] = 'emulated';
+        $this->supported['primary_key'] = true;
+        $this->supported['result_introspection'] = true;
+        $this->supported['prepared_statements'] = true;
+        $this->supported['identifier_quoting'] = true;
+        $this->supported['pattern_escaping'] = true;
+        $this->supported['new_link'] = true;
+
+        $this->options['multi_query'] = false;
+    }
+
+    // }}}
+    // {{{ errorInfo()
+
+    /**
+     * This method is used to collect information about an error
+     *
+     * @param integer $error
+     * @return array
+     * @access public
+     */
+    function errorInfo($error = null)
+    {
+        // Fall back to MDB2_ERROR if there was no mapping.
+        $error_code = MDB2_ERROR;
+
+        $native_msg = '';
+        if (is_resource($error)) {
+            $native_msg = @pg_result_error($error);
+        } elseif ($this->connection) {
+            $native_msg = @pg_last_error($this->connection);
+            if (!$native_msg && @pg_connection_status($this->connection) === PGSQL_CONNECTION_BAD) {
+                $native_msg = 'Database connection has been lost.';
+                $error_code = MDB2_ERROR_CONNECT_FAILED;
+            }
+        }
+
+        static $error_regexps;
+        if (empty($error_regexps)) {
+            $error_regexps = array(
+                '/column .* (of relation .*)?does not exist/i'
+                    => MDB2_ERROR_NOSUCHFIELD,
+                '/(relation|sequence|table).*does not exist|class .* not found/i'
+                    => MDB2_ERROR_NOSUCHTABLE,
+                '/index .* does not exist/'
+                    => MDB2_ERROR_NOT_FOUND,
+                '/relation .* already exists/i'
+                    => MDB2_ERROR_ALREADY_EXISTS,
+                '/(divide|division) by zero$/i'
+                    => MDB2_ERROR_DIVZERO,
+                '/pg_atoi: error in .*: can\'t parse /i'
+                    => MDB2_ERROR_INVALID_NUMBER,
+                '/invalid input syntax for( type)? (integer|numeric)/i'
+                    => MDB2_ERROR_INVALID_NUMBER,
+                '/value .* is out of range for type \w*int/i'
+                    => MDB2_ERROR_INVALID_NUMBER,
+                '/integer out of range/i'
+                    => MDB2_ERROR_INVALID_NUMBER,
+                '/value too long for type character/i'
+                    => MDB2_ERROR_INVALID,
+                '/attribute .* not found|relation .* does not have attribute/i'
+                    => MDB2_ERROR_NOSUCHFIELD,
+                '/column .* specified in USING clause does not exist in (left|right) table/i'
+                    => MDB2_ERROR_NOSUCHFIELD,
+                '/parser: parse error at or near/i'
+                    => MDB2_ERROR_SYNTAX,
+                '/syntax error at/'
+                    => MDB2_ERROR_SYNTAX,
+                '/column reference .* is ambiguous/i'
+                    => MDB2_ERROR_SYNTAX,
+                '/permission denied/'
+                    => MDB2_ERROR_ACCESS_VIOLATION,
+                '/violates not-null constraint/'
+                    => MDB2_ERROR_CONSTRAINT_NOT_NULL,
+                '/violates [\w ]+ constraint/'
+                    => MDB2_ERROR_CONSTRAINT,
+                '/referential integrity violation/'
+                    => MDB2_ERROR_CONSTRAINT,
+                '/more expressions than target columns/i'
+                    => MDB2_ERROR_VALUE_COUNT_ON_ROW,
+            );
+        }
+        if (is_numeric($error) && $error < 0) {
+            $error_code = $error;
+        } else {
+            foreach ($error_regexps as $regexp => $code) {
+                if (preg_match($regexp, $native_msg)) {
+                    $error_code = $code;
+                    break;
+                }
+            }
+        }
+        return array($error_code, null, $native_msg);
+    }
+
+    // }}}
+    // {{{ escape()
+
+    /**
+     * Quotes a string so it can be safely used in a query. It will quote
+     * the text so it can safely be used within a query.
+     *
+     * @param   string  the input string to quote
+     * @param   bool    escape wildcards
+     *
+     * @return  string  quoted string
+     *
+     * @access  public
+     */
+    function escape($text, $escape_wildcards = false)
+    {
+        if ($escape_wildcards) {
+            $text = $this->escapePattern($text);
+        }
+        $connection = $this->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+        if (version_compare(PHP_VERSION, '5.2.0RC5', '>=')) {
+            $text = @pg_escape_string($connection, $text);
+        } else {
+            $text = @pg_escape_string($text);
+        }
+        return $text;
+    }
+
+    // }}}
+    // {{{ beginTransaction()
+
+    /**
+     * Start a transaction or set a savepoint.
+     *
+     * @param   string  name of a savepoint to set
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function beginTransaction($savepoint = null)
+    {
+        $this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
+        if (!is_null($savepoint)) {
+            if (!$this->in_transaction) {
+                return $this->raiseError(MDB2_ERROR_INVALID, null, null,
+                    'savepoint cannot be released when changes are auto committed', __FUNCTION__);
+            }
+            $query = 'SAVEPOINT '.$savepoint;
+            return $this->_doQuery($query, true);
+        } elseif ($this->in_transaction) {
+            return MDB2_OK;  //nothing to do
+        }
+        if (!$this->destructor_registered && $this->opened_persistent) {
+            $this->destructor_registered = true;
+            register_shutdown_function('MDB2_closeOpenTransactions');
+        }
+        $result =& $this->_doQuery('BEGIN', true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        $this->in_transaction = true;
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ commit()
+
+    /**
+     * Commit the database changes done during a transaction that is in
+     * progress or release a savepoint. This function may only be called when
+     * auto-committing is disabled, otherwise it will fail. Therefore, a new
+     * transaction is implicitly started after committing the pending changes.
+     *
+     * @param   string  name of a savepoint to release
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function commit($savepoint = null)
+    {
+        $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
+        if (!$this->in_transaction) {
+            return $this->raiseError(MDB2_ERROR_INVALID, null, null,
+                'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__);
+        }
+        if (!is_null($savepoint)) {
+            $query = 'RELEASE SAVEPOINT '.$savepoint;
+            return $this->_doQuery($query, true);
+        }
+
+        $result =& $this->_doQuery('COMMIT', true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        $this->in_transaction = false;
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ rollback()
+
+    /**
+     * Cancel any database changes done during a transaction or since a specific
+     * savepoint that is in progress. This function may only be called when
+     * auto-committing is disabled, otherwise it will fail. Therefore, a new
+     * transaction is implicitly started after canceling the pending changes.
+     *
+     * @param   string  name of a savepoint to rollback to
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function rollback($savepoint = null)
+    {
+        $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
+        if (!$this->in_transaction) {
+            return $this->raiseError(MDB2_ERROR_INVALID, null, null,
+                'rollback cannot be done changes are auto committed', __FUNCTION__);
+        }
+        if (!is_null($savepoint)) {
+            $query = 'ROLLBACK TO SAVEPOINT '.$savepoint;
+            return $this->_doQuery($query, true);
+        }
+
+        $query = 'ROLLBACK';
+        $result =& $this->_doQuery($query, true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        $this->in_transaction = false;
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function setTransactionIsolation()
+
+    /**
+     * Set the transacton isolation level.
+     *
+     * @param   string  standard isolation level
+     *                  READ UNCOMMITTED (allows dirty reads)
+     *                  READ COMMITTED (prevents dirty reads)
+     *                  REPEATABLE READ (prevents nonrepeatable reads)
+     *                  SERIALIZABLE (prevents phantom reads)
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     * @since   2.1.1
+     */
+    function setTransactionIsolation($isolation)
+    {
+        $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true));
+        switch ($isolation) {
+        case 'READ UNCOMMITTED':
+        case 'READ COMMITTED':
+        case 'REPEATABLE READ':
+        case 'SERIALIZABLE':
+            break;
+        default:
+            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'isolation level is not supported: '.$isolation, __FUNCTION__);
+        }
+
+        $query = "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL $isolation";
+        return $this->_doQuery($query, true);
+    }
+
+    // }}}
+    // {{{ _doConnect()
+
+    /**
+     * Does the grunt work of connecting to the database
+     *
+     * @return mixed connection resource on success, MDB2 Error Object on failure
+     * @access protected
+     **/
+    function _doConnect($database_name, $persistent = false)
+    {
+        if ($database_name == '') {
+            $database_name = 'template1';
+        }
+
+        $protocol = $this->dsn['protocol'] ? $this->dsn['protocol'] : 'tcp';
+
+        $params = array('');
+        if ($protocol == 'tcp') {
+            if ($this->dsn['hostspec']) {
+                $params[0].= 'host=' . $this->dsn['hostspec'];
+            }
+            if ($this->dsn['port']) {
+                $params[0].= ' port=' . $this->dsn['port'];
+            }
+        } elseif ($protocol == 'unix') {
+            // Allow for pg socket in non-standard locations.
+            if ($this->dsn['socket']) {
+                $params[0].= 'host=' . $this->dsn['socket'];
+            }
+            if ($this->dsn['port']) {
+                $params[0].= ' port=' . $this->dsn['port'];
+            }
+        }
+        if ($database_name) {
+            $params[0].= ' dbname=\'' . addslashes($database_name) . '\'';
+        }
+        if ($this->dsn['username']) {
+            $params[0].= ' user=\'' . addslashes($this->dsn['username']) . '\'';
+        }
+        if ($this->dsn['password']) {
+            $params[0].= ' password=\'' . addslashes($this->dsn['password']) . '\'';
+        }
+        if (!empty($this->dsn['options'])) {
+            $params[0].= ' options=' . $this->dsn['options'];
+        }
+        if (!empty($this->dsn['tty'])) {
+            $params[0].= ' tty=' . $this->dsn['tty'];
+        }
+        if (!empty($this->dsn['connect_timeout'])) {
+            $params[0].= ' connect_timeout=' . $this->dsn['connect_timeout'];
+        }
+        if (!empty($this->dsn['sslmode'])) {
+            $params[0].= ' sslmode=' . $this->dsn['sslmode'];
+        }
+        if (!empty($this->dsn['service'])) {
+            $params[0].= ' service=' . $this->dsn['service'];
+        }
+
+        if (!empty($this->dsn['new_link'])
+            && ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true))
+        {
+            if (version_compare(phpversion(), '4.3.0', '>=')) {
+                $params[] = PGSQL_CONNECT_FORCE_NEW;
+            }
+        }
+
+        $connect_function = $persistent ? 'pg_pconnect' : 'pg_connect';
+
+        $connection = @call_user_func_array($connect_function, $params);
+        if (!$connection) {
+            return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
+                'unable to establish a connection', __FUNCTION__);
+        }
+
+       if (empty($this->dsn['disable_iso_date'])) {
+            if (!@pg_query($connection, "SET SESSION DATESTYLE = 'ISO'")) {
+                return $this->raiseError(null, null, null,
+                    'Unable to set date style to iso', __FUNCTION__);
+            }
+       }
+
+        if (!empty($this->dsn['charset'])) {
+            $result = $this->setCharset($this->dsn['charset'], $connection);
+            if (PEAR::isError($result)) {
+                return $result;
+            }
+        }
+
+        return $connection;
+    }
+
+    // }}}
+    // {{{ connect()
+
+    /**
+     * Connect to the database
+     *
+     * @return true on success, MDB2 Error Object on failure
+     * @access public
+     **/
+    function connect()
+    {
+        if (is_resource($this->connection)) {
+            if (count(array_diff($this->connected_dsn, $this->dsn)) == 0
+                && $this->connected_database_name == $this->database_name
+                && ($this->opened_persistent == $this->options['persistent'])
+            ) {
+                return MDB2_OK;
+            }
+            $this->disconnect(false);
+        }
+
+        if (!PEAR::loadExtension($this->phptype)) {
+            return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
+        }
+
+        if ($this->database_name) {
+            $connection = $this->_doConnect($this->database_name, $this->options['persistent']);
+            if (PEAR::isError($connection)) {
+                return $connection;
+            }
+            $this->connection = $connection;
+            $this->connected_dsn = $this->dsn;
+            $this->connected_database_name = $this->database_name;
+            $this->opened_persistent = $this->options['persistent'];
+            $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype;
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ setCharset()
+
+    /**
+     * Set the charset on the current connection
+     *
+     * @param string    charset
+     * @param resource  connection handle
+     *
+     * @return true on success, MDB2 Error Object on failure
+     */
+    function setCharset($charset, $connection = null)
+    {
+        if (is_null($connection)) {
+            $connection = $this->getConnection();
+            if (PEAR::isError($connection)) {
+                return $connection;
+            }
+        }
+
+        $result = @pg_set_client_encoding($connection, $charset);
+        if ($result == -1) {
+            return $this->raiseError(null, null, null,
+                'Unable to set client charset: '.$charset, __FUNCTION__);
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ disconnect()
+
+    /**
+     * Log out and disconnect from the database.
+     *
+     * @param  boolean $force if the disconnect should be forced even if the
+     *                        connection is opened persistently
+     * @return mixed true on success, false if not connected and error
+     *                object on error
+     * @access public
+     */
+    function disconnect($force = true)
+    {
+        if (is_resource($this->connection)) {
+            if ($this->in_transaction) {
+                $dsn = $this->dsn;
+                $database_name = $this->database_name;
+                $persistent = $this->options['persistent'];
+                $this->dsn = $this->connected_dsn;
+                $this->database_name = $this->connected_database_name;
+                $this->options['persistent'] = $this->opened_persistent;
+                $this->rollback();
+                $this->dsn = $dsn;
+                $this->database_name = $database_name;
+                $this->options['persistent'] = $persistent;
+            }
+
+            if (!$this->opened_persistent || $force) {
+                @pg_close($this->connection);
+            }
+        }
+        return parent::disconnect($force);
+    }
+
+    // }}}
+    // {{{ standaloneQuery()
+
+   /**
+     * execute a query as DBA
+     *
+     * @param string $query the SQL query
+     * @param mixed   $types  array that contains the types of the columns in
+     *                        the result set
+     * @param boolean $is_manip  if the query is a manipulation query
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function &standaloneQuery($query, $types = null, $is_manip = false)
+    {
+        $connection = $this->_doConnect('template1', false);
+        if (PEAR::isError($connection)) {
+            $err =& $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
+                'Cannot connect to template1', __FUNCTION__);
+            return $err;
+        }
+
+        $offset = $this->offset;
+        $limit = $this->limit;
+        $this->offset = $this->limit = 0;
+        $query = $this->_modifyQuery($query, $is_manip, $limit, $offset);
+
+        $result =& $this->_doQuery($query, $is_manip, $connection, false);
+        @pg_close($connection);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+
+        if ($is_manip) {
+            $affected_rows =  $this->_affectedRows($connection, $result);
+            return $affected_rows;
+        }
+        $result =& $this->_wrapResult($result, $types, true, false, $limit, $offset);
+        return $result;
+    }
+
+    // }}}
+    // {{{ _doQuery()
+
+    /**
+     * Execute a query
+     * @param string $query  query
+     * @param boolean $is_manip  if the query is a manipulation query
+     * @param resource $connection
+     * @param string $database_name
+     * @return result or error object
+     * @access protected
+     */
+    function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null)
+    {
+        $this->last_query = $query;
+        $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre'));
+        if ($result) {
+            if (PEAR::isError($result)) {
+                return $result;
+            }
+            $query = $result;
+        }
+        if ($this->options['disable_query']) {
+            $result = $is_manip ? 0 : null;
+            return $result;
+        }
+
+        if (is_null($connection)) {
+            $connection = $this->getConnection();
+            if (PEAR::isError($connection)) {
+                return $connection;
+            }
+        }
+
+        $function = $this->options['multi_query'] ? 'pg_send_query' : 'pg_query';
+        $result = @$function($connection, $query);
+        if (!$result) {
+            $err =& $this->raiseError(null, null, null,
+                'Could not execute statement', __FUNCTION__);
+            return $err;
+        } elseif ($this->options['multi_query']) {
+            if (!($result = @pg_get_result($connection))) {
+                $err =& $this->raiseError(null, null, null,
+                        'Could not get the first result from a multi query', __FUNCTION__);
+                return $err;
+            }
+        }
+
+        $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'post', 'result' => $result));
+        return $result;
+    }
+
+    // }}}
+    // {{{ _affectedRows()
+
+    /**
+     * Returns the number of rows affected
+     *
+     * @param resource $result
+     * @param resource $connection
+     * @return mixed MDB2 Error Object or the number of rows affected
+     * @access private
+     */
+    function _affectedRows($connection, $result = null)
+    {
+        if (is_null($connection)) {
+            $connection = $this->getConnection();
+            if (PEAR::isError($connection)) {
+                return $connection;
+            }
+        }
+        return @pg_affected_rows($result);
+    }
+
+    // }}}
+    // {{{ _modifyQuery()
+
+    /**
+     * Changes a query string for various DBMS specific reasons
+     *
+     * @param string $query  query to modify
+     * @param boolean $is_manip  if it is a DML query
+     * @param integer $limit  limit the number of rows
+     * @param integer $offset  start reading from given offset
+     * @return string modified query
+     * @access protected
+     */
+    function _modifyQuery($query, $is_manip, $limit, $offset)
+    {
+        if ($limit > 0
+            && !preg_match('/LIMIT\s*\d(?:\s*(?:,|OFFSET)\s*\d+)?(?:[^\)]*)?$/i', $query)
+        ) {
+            $query = rtrim($query);
+            if (substr($query, -1) == ';') {
+                $query = substr($query, 0, -1);
+            }
+            if ($is_manip) {
+                $query = $this->_modifyManipQuery($query, $limit);
+            } else {
+                $query.= " LIMIT $limit OFFSET $offset";
+            }
+        }
+        return $query;
+    }
+    
+    // }}}
+    // {{{ _modifyManipQuery()
+    
+    /**
+     * Changes a manip query string for various DBMS specific reasons
+     *
+     * @param string $query  query to modify
+     * @param integer $limit  limit the number of rows
+     * @return string modified query
+     * @access protected
+     */
+    function _modifyManipQuery($query, $limit)
+    {
+        $pos = strpos(strtolower($query), 'where');
+        $where = $pos ? substr($query, $pos) : '';
+
+        $manip_clause = '(\bDELETE\b\s+(?:\*\s+)?\bFROM\b|\bUPDATE\b)';
+        $from_clause  = '([\w\.]+)';
+        $where_clause = '(?:(.*)\bWHERE\b\s+(.*))|(.*)';
+        $pattern = '/^'. $manip_clause . '\s+' . $from_clause .'(?:\s)*(?:'. $where_clause .')?$/i';
+        $matches = preg_match($pattern, $query, $match);
+        if ($matches) {
+            $manip = $match[1];
+            $from  = $match[2];
+            $what  = (count($matches) == 6) ? $match[5] : $match[3];
+            return $manip.' '.$from.' '.$what.' WHERE ctid=(SELECT ctid FROM '.$from.' '.$where.' LIMIT '.$limit.')';
+        }
+        //return error?
+        return $query;
+    }
+
+    // }}}
+    // {{{ getServerVersion()
+
+    /**
+     * return version information about the server
+     *
+     * @param bool   $native  determines if the raw version string should be returned
+     * @return mixed array/string with version information or MDB2 error object
+     * @access public
+     */
+    function getServerVersion($native = false)
+    {
+        $query = 'SHOW SERVER_VERSION';
+        if ($this->connected_server_info) {
+            $server_info = $this->connected_server_info;
+        } else {
+            $server_info = $this->queryOne($query, 'text');
+            if (PEAR::isError($server_info)) {
+                return $server_info;
+            }
+        }
+        // cache server_info
+        $this->connected_server_info = $server_info;
+        if (!$native && !PEAR::isError($server_info)) {
+            $tmp = explode('.', $server_info, 3);
+            if (empty($tmp[2])
+                && isset($tmp[1])
+                && preg_match('/(\d+)(.*)/', $tmp[1], $tmp2)
+            ) {
+                $server_info = array(
+                    'major' => $tmp[0],
+                    'minor' => $tmp2[1],
+                    'patch' => null,
+                    'extra' => $tmp2[2],
+                    'native' => $server_info,
+                );
+            } else {
+                $server_info = array(
+                    'major' => isset($tmp[0]) ? $tmp[0] : null,
+                    'minor' => isset($tmp[1]) ? $tmp[1] : null,
+                    'patch' => isset($tmp[2]) ? $tmp[2] : null,
+                    'extra' => null,
+                    'native' => $server_info,
+                );
+            }
+        }
+        return $server_info;
+    }
+
+    // }}}
+    // {{{ prepare()
+
+    /**
+     * Prepares a query for multiple execution with execute().
+     * With some database backends, this is emulated.
+     * prepare() requires a generic query as string like
+     * 'INSERT INTO numbers VALUES(?,?)' or
+     * 'INSERT INTO numbers VALUES(:foo,:bar)'.
+     * The ? and :[a-zA-Z] and  are placeholders which can be set using
+     * bindParam() and the query can be send off using the execute() method.
+     *
+     * @param string $query the query to prepare
+     * @param mixed   $types  array that contains the types of the placeholders
+     * @param mixed   $result_types  array that contains the types of the columns in
+     *                        the result set or MDB2_PREPARE_RESULT, if set to
+     *                        MDB2_PREPARE_MANIP the query is handled as a manipulation query
+     * @param mixed   $lobs   key (field) value (parameter) pair for all lob placeholders
+     * @return mixed resource handle for the prepared query on success, a MDB2
+     *        error on failure
+     * @access public
+     * @see bindParam, execute
+     */
+    function &prepare($query, $types = null, $result_types = null, $lobs = array())
+    {
+        if ($this->options['emulate_prepared']) {
+            $obj =& parent::prepare($query, $types, $result_types, $lobs);
+            return $obj;
+        }
+        $is_manip = ($result_types === MDB2_PREPARE_MANIP);
+        $offset = $this->offset;
+        $limit = $this->limit;
+        $this->offset = $this->limit = 0;
+        $result = $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'pre'));
+        if ($result) {
+            if (PEAR::isError($result)) {
+                return $result;
+            }
+            $query = $result;
+        }
+        $pgtypes = function_exists('pg_prepare') ? false : array();
+        if ($pgtypes !== false && !empty($types)) {
+            $this->loadModule('Datatype', null, true);
+        }
+        $query = $this->_modifyQuery($query, $is_manip, $limit, $offset);
+        $placeholder_type_guess = $placeholder_type = null;
+        $question = '?';
+        $colon = ':';
+        $positions = array();
+        $position = $parameter = 0;
+        while ($position < strlen($query)) {
+            $q_position = strpos($query, $question, $position);
+            $c_position = strpos($query, $colon, $position);
+            if ($q_position && $c_position) {
+                $p_position = min($q_position, $c_position);
+            } elseif ($q_position) {
+                $p_position = $q_position;
+            } elseif ($c_position) {
+                $p_position = $c_position;
+            } else {
+                break;
+            }
+            if (is_null($placeholder_type)) {
+                $placeholder_type_guess = $query[$p_position];
+            }
+            
+            $new_pos = $this->_skipDelimitedStrings($query, $position, $p_position);
+            if (PEAR::isError($new_pos)) {
+                return $new_pos;
+            }
+            if ($new_pos != $position) {
+                $position = $new_pos;
+                continue; //evaluate again starting from the new position
+            }
+
+            if ($query[$position] == $placeholder_type_guess) {
+                if (is_null($placeholder_type)) {
+                    $placeholder_type = $query[$p_position];
+                    $question = $colon = $placeholder_type;
+                    if (!empty($types) && is_array($types)) {
+                        if ($placeholder_type == ':') {
+                        } else {
+                            $types = array_values($types);
+                        }
+                    }
+                }
+                if ($placeholder_type_guess == '?') {
+                    $length = 1;
+                    $name = $parameter;
+                } else {
+                    $name = preg_replace('/^.{'.($position+1).'}([a-z0-9_]+).*$/si', '\\1', $query);
+                    if ($name === '') {
+                        $err =& $this->raiseError(MDB2_ERROR_SYNTAX, null, null,
+                            'named parameter with an empty name', __FUNCTION__);
+                        return $err;
+                    }
+                    $length = strlen($name) + 1;
+                }
+                if ($pgtypes !== false) {
+                    if (is_array($types) && array_key_exists($name, $types)) {
+                        $pgtypes[] = $this->datatype->mapPrepareDatatype($types[$name]);
+                    } elseif (is_array($types) && array_key_exists($parameter, $types)) {
+                        $pgtypes[] = $this->datatype->mapPrepareDatatype($types[$parameter]);
+                    } else {
+                        $pgtypes[] = 'text';
+                    }
+                }
+                if (($key_parameter = array_search($name, $positions))) {
+                    $next_parameter = 1;
+                    foreach ($positions as $key => $value) {
+                        if ($key_parameter == $key) {
+                            break;
+                        }
+                        ++$next_parameter;
+                    }
+                } else {
+                    ++$parameter;
+                    $next_parameter = $parameter;
+                    $positions[] = $name;
+                }
+                $query = substr_replace($query, '$'.$parameter, $position, $length);
+                $position = $p_position + strlen($parameter);
+            } else {
+                $position = $p_position;
+            }
+        }
+        $connection = $this->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+
+        $statement_name = sprintf($this->options['statement_format'], $this->phptype, md5(time() + rand()));
+        $statement_name = strtolower($statement_name);
+        if ($pgtypes === false) {
+            $result = @pg_prepare($connection, $statement_name, $query);
+            if (!$result) {
+                $err =& $this->raiseError(null, null, null,
+                    'Unable to create prepared statement handle', __FUNCTION__);
+                return $err;
+            }
+        } else {
+            $types_string = '';
+            if ($pgtypes) {
+                $types_string = ' ('.implode(', ', $pgtypes).') ';
+            }
+            $query = 'PREPARE '.$statement_name.$types_string.' AS '.$query;
+            $statement =& $this->_doQuery($query, true, $connection);
+            if (PEAR::isError($statement)) {
+                return $statement;
+            }
+        }
+
+        $class_name = 'MDB2_Statement_'.$this->phptype;
+        $obj =& new $class_name($this, $statement_name, $positions, $query, $types, $result_types, $is_manip, $limit, $offset);
+        $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'post', 'result' => $obj));
+        return $obj;
+    }
+
+    // }}}
+    // {{{ function getSequenceName($sqn)
+
+    /**
+     * adds sequence name formatting to a sequence name
+     *
+     * @param   string  name of the sequence
+     *
+     * @return  string  formatted sequence name
+     *
+     * @access  public
+     */
+    function getSequenceName($sqn)
+    {
+        list($table, $field) = explode('_', $sqn);
+        $query = "SELECT substring((SELECT substring(pg_get_expr(d.adbin, d.adrelid) for 128)
+                           FROM pg_attrdef d
+                          WHERE d.adrelid = a.attrelid
+                            AND d.adnum = a.attnum
+                            AND a.atthasdef
+                        ) FROM 'nextval[^\']*\'([^\']*)')
+                    FROM pg_attribute a
+                LEFT JOIN pg_class c ON c.oid = a.attrelid
+                LEFT JOIN pg_attrdef d ON d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef
+                   WHERE (c.relname = ".$this->quote($sqn, 'text');
+        if (!empty($field)) {
+            $query .= " OR (c.relname = ".$this->quote($table, 'text')." AND a.attname = ".$this->quote($field, 'text').")";
+        }
+        $query .= "      )
+                     AND NOT a.attisdropped
+                     AND a.attnum > 0
+                     AND pg_get_expr(d.adbin, d.adrelid) LIKE 'nextval%'
+                ORDER BY a.attnum";
+        $seqname = $this->queryOne($query);
+        if (!PEAR::isError($seqname) && !empty($seqname) && is_string($seqname)) {
+            return $seqname;
+        }
+
+        return sprintf($this->options['seqname_format'],
+            preg_replace('/[^\w\$.]/i', '_', $sqn));
+    }
+
+    // }}}
+    // {{{ nextID()
+
+    /**
+     * Returns the next free id of a sequence
+     *
+     * @param string $seq_name name of the sequence
+     * @param boolean $ondemand when true the sequence is
+     *                          automatic created, if it
+     *                          not exists
+     * @return mixed MDB2 Error Object or id
+     * @access public
+     */
+    function nextID($seq_name, $ondemand = true)
+    {
+        $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
+        $query = "SELECT NEXTVAL('$sequence_name')";
+        $this->expectError(MDB2_ERROR_NOSUCHTABLE);
+        $result = $this->queryOne($query, 'integer');
+        $this->popExpect();
+        if (PEAR::isError($result)) {
+            if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) {
+                $this->loadModule('Manager', null, true);
+                $result = $this->manager->createSequence($seq_name);
+                if (PEAR::isError($result)) {
+                    return $this->raiseError($result, null, null,
+                        'on demand sequence could not be created', __FUNCTION__);
+                }
+                return $this->nextId($seq_name, false);
+            }
+        }
+        return $result;
+    }
+
+    // }}}
+    // {{{ lastInsertID()
+
+    /**
+     * Returns the autoincrement ID if supported or $id or fetches the current
+     * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
+     *
+     * @param string $table name of the table into which a new row was inserted
+     * @param string $field name of the field into which a new row was inserted
+     * @return mixed MDB2 Error Object or id
+     * @access public
+     */
+    function lastInsertID($table = null, $field = null)
+    {
+        if (empty($table) && empty($field)) {
+            return $this->queryOne('SELECT lastval()', 'integer');
+        }
+        $seq = $table.(empty($field) ? '' : '_'.$field);
+        $sequence_name = $this->getSequenceName($seq);
+        return $this->queryOne("SELECT currval('$sequence_name')", 'integer');
+    }
+
+    // }}}
+    // {{{ currID()
+
+    /**
+     * Returns the current id of a sequence
+     *
+     * @param string $seq_name name of the sequence
+     * @return mixed MDB2 Error Object or id
+     * @access public
+     */
+    function currID($seq_name)
+    {
+        $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
+        return $this->queryOne("SELECT last_value FROM $sequence_name", 'integer');
+    }
+}
+
+/**
+ * MDB2 PostGreSQL result driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Paul Cooper <pgc@ucecom.com>
+ */
+class MDB2_Result_pgsql extends MDB2_Result_Common
+{
+    // }}}
+    // {{{ fetchRow()
+
+    /**
+     * Fetch a row and insert the data into an existing array.
+     *
+     * @param int       $fetchmode  how the array data should be indexed
+     * @param int    $rownum    number of the row where the data can be found
+     * @return int data array on success, a MDB2 error on failure
+     * @access public
+     */
+    function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)
+    {
+        if (!is_null($rownum)) {
+            $seek = $this->seek($rownum);
+            if (PEAR::isError($seek)) {
+                return $seek;
+            }
+        }
+        if ($fetchmode == MDB2_FETCHMODE_DEFAULT) {
+            $fetchmode = $this->db->fetchmode;
+        }
+        if ($fetchmode & MDB2_FETCHMODE_ASSOC) {
+            $row = @pg_fetch_array($this->result, null, PGSQL_ASSOC);
+            if (is_array($row)
+                && $this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE
+            ) {
+                $row = array_change_key_case($row, $this->db->options['field_case']);
+            }
+        } else {
+            $row = @pg_fetch_row($this->result);
+        }
+        if (!$row) {
+            if ($this->result === false) {
+                $err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                    'resultset has already been freed', __FUNCTION__);
+                return $err;
+            }
+            $null = null;
+            return $null;
+        }
+        $mode = $this->db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL;
+        $rtrim = false;
+        if ($this->db->options['portability'] & MDB2_PORTABILITY_RTRIM) {
+            if (empty($this->types)) {
+                $mode += MDB2_PORTABILITY_RTRIM;
+            } else {
+                $rtrim = true;
+            }
+        }
+        if ($mode) {
+            $this->db->_fixResultArrayValues($row, $mode);
+        }
+        if (!empty($this->types)) {
+            $row = $this->db->datatype->convertResultRow($this->types, $row, $rtrim);
+        }
+        if (!empty($this->values)) {
+            $this->_assignBindColumns($row);
+        }
+        if ($fetchmode === MDB2_FETCHMODE_OBJECT) {
+            $object_class = $this->db->options['fetch_class'];
+            if ($object_class == 'stdClass') {
+                $row = (object) $row;
+            } else {
+                $row = &new $object_class($row);
+            }
+        }
+        ++$this->rownum;
+        return $row;
+    }
+
+    // }}}
+    // {{{ _getColumnNames()
+
+    /**
+     * Retrieve the names of columns returned by the DBMS in a query result.
+     *
+     * @return  mixed   Array variable that holds the names of columns as keys
+     *                  or an MDB2 error on failure.
+     *                  Some DBMS may not return any columns when the result set
+     *                  does not contain any rows.
+     * @access private
+     */
+    function _getColumnNames()
+    {
+        $columns = array();
+        $numcols = $this->numCols();
+        if (PEAR::isError($numcols)) {
+            return $numcols;
+        }
+        for ($column = 0; $column < $numcols; $column++) {
+            $column_name = @pg_field_name($this->result, $column);
+            $columns[$column_name] = $column;
+        }
+        if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $columns = array_change_key_case($columns, $this->db->options['field_case']);
+        }
+        return $columns;
+    }
+
+    // }}}
+    // {{{ numCols()
+
+    /**
+     * Count the number of columns returned by the DBMS in a query result.
+     *
+     * @access public
+     * @return mixed integer value with the number of columns, a MDB2 error
+     *                       on failure
+     */
+    function numCols()
+    {
+        $cols = @pg_num_fields($this->result);
+        if (is_null($cols)) {
+            if ($this->result === false) {
+                return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                    'resultset has already been freed', __FUNCTION__);
+            } elseif (is_null($this->result)) {
+                return count($this->types);
+            }
+            return $this->db->raiseError(null, null, null,
+                'Could not get column count', __FUNCTION__);
+        }
+        return $cols;
+    }
+
+    // }}}
+    // {{{ nextResult()
+
+    /**
+     * Move the internal result pointer to the next available result
+     *
+     * @return true on success, false if there is no more result set or an error object on failure
+     * @access public
+     */
+    function nextResult()
+    {
+        $connection = $this->db->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+
+        if (!($this->result = @pg_get_result($connection))) {
+            return false;
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ free()
+
+    /**
+     * Free the internal resources associated with result.
+     *
+     * @return boolean true on success, false if result is invalid
+     * @access public
+     */
+    function free()
+    {
+        if (is_resource($this->result) && $this->db->connection) {
+            $free = @pg_free_result($this->result);
+            if ($free === false) {
+                return $this->db->raiseError(null, null, null,
+                    'Could not free result', __FUNCTION__);
+            }
+        }
+        $this->result = false;
+        return MDB2_OK;
+    }
+}
+
+/**
+ * MDB2 PostGreSQL buffered result driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Paul Cooper <pgc@ucecom.com>
+ */
+class MDB2_BufferedResult_pgsql extends MDB2_Result_pgsql
+{
+    // {{{ seek()
+
+    /**
+     * Seek to a specific row in a result set
+     *
+     * @param int    $rownum    number of the row where the data can be found
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function seek($rownum = 0)
+    {
+        if ($this->rownum != ($rownum - 1) && !@pg_result_seek($this->result, $rownum)) {
+            if ($this->result === false) {
+                return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                    'resultset has already been freed', __FUNCTION__);
+            } elseif (is_null($this->result)) {
+                return MDB2_OK;
+            }
+            return $this->db->raiseError(MDB2_ERROR_INVALID, null, null,
+                'tried to seek to an invalid row number ('.$rownum.')', __FUNCTION__);
+        }
+        $this->rownum = $rownum - 1;
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ valid()
+
+    /**
+     * Check if the end of the result set has been reached
+     *
+     * @return mixed true or false on sucess, a MDB2 error on failure
+     * @access public
+     */
+    function valid()
+    {
+        $numrows = $this->numRows();
+        if (PEAR::isError($numrows)) {
+            return $numrows;
+        }
+        return $this->rownum < ($numrows - 1);
+    }
+
+    // }}}
+    // {{{ numRows()
+
+    /**
+     * Returns the number of rows in a result object
+     *
+     * @return mixed MDB2 Error Object or the number of rows
+     * @access public
+     */
+    function numRows()
+    {
+        $rows = @pg_num_rows($this->result);
+        if (is_null($rows)) {
+            if ($this->result === false) {
+                return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                    'resultset has already been freed', __FUNCTION__);
+            } elseif (is_null($this->result)) {
+                return 0;
+            }
+            return $this->db->raiseError(null, null, null,
+                'Could not get row count', __FUNCTION__);
+        }
+        return $rows;
+    }
+}
+
+/**
+ * MDB2 PostGreSQL statement driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Paul Cooper <pgc@ucecom.com>
+ */
+class MDB2_Statement_pgsql extends MDB2_Statement_Common
+{
+    // {{{ _execute()
+
+    /**
+     * Execute a prepared query statement helper method.
+     *
+     * @param mixed $result_class string which specifies which result class to use
+     * @param mixed $result_wrap_class string which specifies which class to wrap results in
+     * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
+     * @access private
+     */
+    function &_execute($result_class = true, $result_wrap_class = false)
+    {
+        if (is_null($this->statement)) {
+            $result =& parent::_execute($result_class, $result_wrap_class);
+            return $result;
+        }
+        $this->db->last_query = $this->query;
+        $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'pre', 'parameters' => $this->values));
+        if ($this->db->getOption('disable_query')) {
+            $result = $this->is_manip ? 0 : null;
+            return $result;
+        }
+
+        $connection = $this->db->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+
+        $query = false;
+        $parameters = array();
+        // todo: disabled until pg_execute() bytea issues are cleared up
+        if (true || !function_exists('pg_execute')) {
+            $query = 'EXECUTE '.$this->statement;
+        }
+        if (!empty($this->positions)) {
+            foreach ($this->positions as $parameter) {
+                if (!array_key_exists($parameter, $this->values)) {
+                    return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                        'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__);
+                }
+                $value = $this->values[$parameter];
+                $type = array_key_exists($parameter, $this->types) ? $this->types[$parameter] : null;
+                if (is_resource($value) || $type == 'clob' || $type == 'blob') {
+                    if (!is_resource($value) && preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) {
+                        if ($match[1] == 'file://') {
+                            $value = $match[2];
+                        }
+                        $value = @fopen($value, 'r');
+                        $close = true;
+                    }
+                    if (is_resource($value)) {
+                        $data = '';
+                        while (!@feof($value)) {
+                            $data.= @fread($value, $this->db->options['lob_buffer_length']);
+                        }
+                        if ($close) {
+                            @fclose($value);
+                        }
+                        $value = $data;
+                    }
+                }
+                $parameters[] = $this->db->quote($value, $type, $query);
+            }
+            if ($query) {
+                $query.= ' ('.implode(', ', $parameters).')';
+            }
+        }
+
+        if (!$query) {
+            $result = @pg_execute($connection, $this->statement, $parameters);
+            if (!$result) {
+                $err =& $this->db->raiseError(null, null, null,
+                    'Unable to execute statement', __FUNCTION__);
+                return $err;
+            }
+        } else {
+            $result = $this->db->_doQuery($query, $this->is_manip, $connection);
+            if (PEAR::isError($result)) {
+                return $result;
+            }
+        }
+
+        if ($this->is_manip) {
+            $affected_rows = $this->db->_affectedRows($connection, $result);
+            return $affected_rows;
+        }
+
+        $result =& $this->db->_wrapResult($result, $this->result_types,
+            $result_class, $result_wrap_class, $this->limit, $this->offset);
+        $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'post', 'result' => $result));
+        return $result;
+    }
+
+    // }}}
+    // {{{ free()
+
+    /**
+     * Release resources allocated for the specified prepared query.
+     *
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function free()
+    {
+        if (is_null($this->positions)) {
+            return $this->db->raiseError(MDB2_ERROR, null, null,
+                'Prepared statement has already been freed', __FUNCTION__);
+        }
+        $result = MDB2_OK;
+
+        if (!is_null($this->statement)) {
+            $connection = $this->db->getConnection();
+            if (PEAR::isError($connection)) {
+                return $connection;
+            }
+            $query = 'DEALLOCATE PREPARE '.$this->statement;
+            $result = $this->db->_doQuery($query, true, $connection);
+        }
+
+        parent::free();
+        return $result;
+    }
+}
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/sqlite.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Driver/sqlite.php
new file mode 100644 (file)
index 0000000..2f4d72b
--- /dev/null
@@ -0,0 +1,1073 @@
+<?php
+// vim: set et ts=4 sw=4 fdm=marker:
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: sqlite.php,v 1.149 2007/05/02 22:00:08 quipo Exp $
+//
+
+/**
+ * MDB2 SQLite driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Driver_sqlite extends MDB2_Driver_Common
+{
+    // {{{ properties
+    var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => "'", 'escape_pattern' => false);
+
+    var $identifier_quoting = array('start' => '"', 'end' => '"', 'escape' => '"');
+
+    var $_lasterror = '';
+
+    var $fix_assoc_fields_names = false;
+
+    // }}}
+    // {{{ constructor
+
+    /**
+     * Constructor
+     */
+    function __construct()
+    {
+        parent::__construct();
+
+        $this->phptype = 'sqlite';
+        $this->dbsyntax = 'sqlite';
+
+        $this->supported['sequences'] = 'emulated';
+        $this->supported['indexes'] = true;
+        $this->supported['affected_rows'] = true;
+        $this->supported['summary_functions'] = true;
+        $this->supported['order_by_text'] = true;
+        $this->supported['current_id'] = 'emulated';
+        $this->supported['limit_queries'] = true;
+        $this->supported['LOBs'] = true;
+        $this->supported['replace'] = true;
+        $this->supported['transactions'] = true;
+        $this->supported['savepoints'] = false;
+        $this->supported['sub_selects'] = true;
+        $this->supported['auto_increment'] = true;
+        $this->supported['primary_key'] = false; // requires alter table implementation
+        $this->supported['result_introspection'] = false; // not implemented
+        $this->supported['prepared_statements'] = 'emulated';
+        $this->supported['identifier_quoting'] = true;
+        $this->supported['pattern_escaping'] = false;
+        $this->supported['new_link'] = false;
+
+        $this->options['base_transaction_name'] = '___php_MDB2_sqlite_auto_commit_off';
+        $this->options['fixed_float'] = 0;
+        $this->options['database_path'] = '';
+        $this->options['database_extension'] = '';
+        $this->options['server_version'] = '';
+    }
+
+    // }}}
+    // {{{ errorInfo()
+
+    /**
+     * This method is used to collect information about an error
+     *
+     * @param integer $error
+     * @return array
+     * @access public
+     */
+    function errorInfo($error = null)
+    {
+        $native_code = null;
+        if ($this->connection) {
+            $native_code = @sqlite_last_error($this->connection);
+        }
+        $native_msg = $this->_lasterror
+            ? html_entity_decode($this->_lasterror) : @sqlite_error_string($native_code);
+            
+        // PHP 5.2+ prepends the function name to $php_errormsg, so we need
+        // this hack to work around it, per bug #9599.
+        $native_msg = preg_replace('/^sqlite[a-z_]+\(\): /', '', $native_msg);
+
+        if (is_null($error)) {
+            static $error_regexps;
+            if (empty($error_regexps)) {
+                $error_regexps = array(
+                    '/^no such table:/' => MDB2_ERROR_NOSUCHTABLE,
+                    '/^no such index:/' => MDB2_ERROR_NOT_FOUND,
+                    '/^(table|index) .* already exists$/' => MDB2_ERROR_ALREADY_EXISTS,
+                    '/PRIMARY KEY must be unique/i' => MDB2_ERROR_CONSTRAINT,
+                    '/is not unique/' => MDB2_ERROR_CONSTRAINT,
+                    '/columns .* are not unique/i' => MDB2_ERROR_CONSTRAINT,
+                    '/uniqueness constraint failed/' => MDB2_ERROR_CONSTRAINT,
+                    '/may not be NULL/' => MDB2_ERROR_CONSTRAINT_NOT_NULL,
+                    '/^no such column:/' => MDB2_ERROR_NOSUCHFIELD,
+                    '/column not present in both tables/i' => MDB2_ERROR_NOSUCHFIELD,
+                    '/^near ".*": syntax error$/' => MDB2_ERROR_SYNTAX,
+                    '/[0-9]+ values for [0-9]+ columns/i' => MDB2_ERROR_VALUE_COUNT_ON_ROW,
+                 );
+            }
+            foreach ($error_regexps as $regexp => $code) {
+                if (preg_match($regexp, $native_msg)) {
+                    $error = $code;
+                    break;
+                }
+            }
+        }
+        return array($error, $native_code, $native_msg);
+    }
+
+    // }}}
+    // {{{ escape()
+
+    /**
+     * Quotes a string so it can be safely used in a query. It will quote
+     * the text so it can safely be used within a query.
+     *
+     * @param   string  the input string to quote
+     * @param   bool    escape wildcards
+     *
+     * @return  string  quoted string
+     *
+     * @access  public
+     */
+    function escape($text, $escape_wildcards = false)
+    {
+        $text = @sqlite_escape_string($text);
+        return $text;
+    }
+
+    // }}}
+    // {{{ beginTransaction()
+
+    /**
+     * Start a transaction or set a savepoint.
+     *
+     * @param   string  name of a savepoint to set
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function beginTransaction($savepoint = null)
+    {
+        $this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
+        if (!is_null($savepoint)) {
+            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'savepoints are not supported', __FUNCTION__);
+        } elseif ($this->in_transaction) {
+            return MDB2_OK;  //nothing to do
+        }
+        if (!$this->destructor_registered && $this->opened_persistent) {
+            $this->destructor_registered = true;
+            register_shutdown_function('MDB2_closeOpenTransactions');
+        }
+        $query = 'BEGIN TRANSACTION '.$this->options['base_transaction_name'];
+        $result =& $this->_doQuery($query, true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        $this->in_transaction = true;
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ commit()
+
+    /**
+     * Commit the database changes done during a transaction that is in
+     * progress or release a savepoint. This function may only be called when
+     * auto-committing is disabled, otherwise it will fail. Therefore, a new
+     * transaction is implicitly started after committing the pending changes.
+     *
+     * @param   string  name of a savepoint to release
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function commit($savepoint = null)
+    {
+        $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
+        if (!$this->in_transaction) {
+            return $this->raiseError(MDB2_ERROR_INVALID, null, null,
+                'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__);
+        }
+        if (!is_null($savepoint)) {
+            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'savepoints are not supported', __FUNCTION__);
+        }
+
+        $query = 'COMMIT TRANSACTION '.$this->options['base_transaction_name'];
+        $result =& $this->_doQuery($query, true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        $this->in_transaction = false;
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{
+
+    /**
+     * Cancel any database changes done during a transaction or since a specific
+     * savepoint that is in progress. This function may only be called when
+     * auto-committing is disabled, otherwise it will fail. Therefore, a new
+     * transaction is implicitly started after canceling the pending changes.
+     *
+     * @param   string  name of a savepoint to rollback to
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     */
+    function rollback($savepoint = null)
+    {
+        $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
+        if (!$this->in_transaction) {
+            return $this->raiseError(MDB2_ERROR_INVALID, null, null,
+                'rollback cannot be done changes are auto committed', __FUNCTION__);
+        }
+        if (!is_null($savepoint)) {
+            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'savepoints are not supported', __FUNCTION__);
+        }
+
+        $query = 'ROLLBACK TRANSACTION '.$this->options['base_transaction_name'];
+        $result =& $this->_doQuery($query, true);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        $this->in_transaction = false;
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ function setTransactionIsolation()
+
+    /**
+     * Set the transacton isolation level.
+     *
+     * @param   string  standard isolation level
+     *                  READ UNCOMMITTED (allows dirty reads)
+     *                  READ COMMITTED (prevents dirty reads)
+     *                  REPEATABLE READ (prevents nonrepeatable reads)
+     *                  SERIALIZABLE (prevents phantom reads)
+     * @return  mixed   MDB2_OK on success, a MDB2 error on failure
+     *
+     * @access  public
+     * @since   2.1.1
+     */
+    function setTransactionIsolation($isolation)
+    {
+        $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true));
+        switch ($isolation) {
+        case 'READ UNCOMMITTED':
+            $isolation = 0;
+            break;
+        case 'READ COMMITTED':
+        case 'REPEATABLE READ':
+        case 'SERIALIZABLE':
+            $isolation = 1;
+            break;
+        default:
+            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'isolation level is not supported: '.$isolation, __FUNCTION__);
+        }
+
+        $query = "PRAGMA read_uncommitted=$isolation";
+        return $this->_doQuery($query, true);
+    }
+
+    // }}}
+    // {{{ getDatabaseFile()
+
+    /**
+     * Builds the string with path+dbname+extension
+     *
+     * @return string full database path+file
+     * @access protected
+     */
+    function _getDatabaseFile($database_name)
+    {
+        if ($database_name === '' || $database_name === ':memory:') {
+            return $database_name;
+        }
+        return $this->options['database_path'].$database_name.$this->options['database_extension'];
+    }
+
+    // }}}
+    // {{{ connect()
+
+    /**
+     * Connect to the database
+     *
+     * @return true on success, MDB2 Error Object on failure
+     **/
+    function connect()
+    {
+        $database_file = $this->_getDatabaseFile($this->database_name);
+        if (is_resource($this->connection)) {
+            if (count(array_diff($this->connected_dsn, $this->dsn)) == 0
+                && $this->connected_database_name == $database_file
+                && $this->opened_persistent == $this->options['persistent']
+            ) {
+                return MDB2_OK;
+            }
+            $this->disconnect(false);
+        }
+
+        if (!PEAR::loadExtension($this->phptype)) {
+            return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
+        }
+
+        if (!empty($this->database_name)) {
+            if ($database_file !== ':memory:') {
+                if (!file_exists($database_file)) {
+                    if (!touch($database_file)) {
+                        return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                            'Could not create database file', __FUNCTION__);
+                    }
+                    if (!isset($this->dsn['mode'])
+                        || !is_numeric($this->dsn['mode'])
+                    ) {
+                        $mode = 0644;
+                    } else {
+                        $mode = octdec($this->dsn['mode']);
+                    }
+                    if (!chmod($database_file, $mode)) {
+                        return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                            'Could not be chmodded database file', __FUNCTION__);
+                    }
+                    if (!file_exists($database_file)) {
+                        return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
+                            'Could not be found database file', __FUNCTION__);
+                    }
+                }
+                if (!is_file($database_file)) {
+                    return $this->raiseError(MDB2_ERROR_INVALID, null, null,
+                            'Database is a directory name', __FUNCTION__);
+                }
+                if (!is_readable($database_file)) {
+                    return $this->raiseError(MDB2_ERROR_ACCESS_VIOLATION, null, null,
+                            'Could not read database file', __FUNCTION__);
+                }
+            }
+
+            $connect_function = ($this->options['persistent'] ? 'sqlite_popen' : 'sqlite_open');
+            $php_errormsg = '';
+            if (version_compare('5.1.0', PHP_VERSION, '>')) {
+                @ini_set('track_errors', true);
+                $connection = @$connect_function($database_file);
+                @ini_restore('track_errors');
+            } else {
+                $connection = @$connect_function($database_file, 0666, $php_errormsg);
+            }
+            $this->_lasterror = $php_errormsg;
+            if (!$connection) {
+                return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
+                'unable to establish a connection', __FUNCTION__);
+            }
+
+            if (!empty($this->dsn['charset'])) {
+                $result = $this->setCharset($this->dsn['charset'], $connection);
+                if (PEAR::isError($result)) {
+                    return $result;
+                }
+            }
+
+            $this->connection = $connection;
+            $this->connected_dsn = $this->dsn;
+            $this->connected_database_name = $database_file;
+            $this->opened_persistent = $this->getoption('persistent');
+            $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype;
+        }
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ disconnect()
+
+    /**
+     * Log out and disconnect from the database.
+     *
+     * @param  boolean $force if the disconnect should be forced even if the
+     *                        connection is opened persistently
+     * @return mixed true on success, false if not connected and error
+     *                object on error
+     * @access public
+     */
+    function disconnect($force = true)
+    {
+        if (is_resource($this->connection)) {
+            if ($this->in_transaction) {
+                $dsn = $this->dsn;
+                $database_name = $this->database_name;
+                $persistent = $this->options['persistent'];
+                $this->dsn = $this->connected_dsn;
+                $this->database_name = $this->connected_database_name;
+                $this->options['persistent'] = $this->opened_persistent;
+                $this->rollback();
+                $this->dsn = $dsn;
+                $this->database_name = $database_name;
+                $this->options['persistent'] = $persistent;
+            }
+
+            if (!$this->opened_persistent || $force) {
+                @sqlite_close($this->connection);
+            }
+        }
+        return parent::disconnect($force);
+    }
+
+    // }}}
+    // {{{ getConnection()
+
+    /**
+     * Returns a native connection
+     *
+     * @return  mixed   a valid MDB2 connection object,
+     *                  or a MDB2 error object on error
+     * @access  public
+     */
+    function getConnection()
+    {
+        $connection = parent::getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+
+        $fix_assoc_fields_names = $this->options['portability'] & MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES;
+        if ($fix_assoc_fields_names !== $this->fix_assoc_fields_names) {
+            @sqlite_query("PRAGMA short_column_names = $fix_assoc_fields_names;", $connection);
+            $this->fix_assoc_fields_names = $fix_assoc_fields_names;
+        }
+
+        return $connection;
+    }
+
+    // }}}
+    // {{{ _doQuery()
+
+    /**
+     * Execute a query
+     * @param string $query  query
+     * @param boolean $is_manip  if the query is a manipulation query
+     * @param resource $connection
+     * @param string $database_name
+     * @return result or error object
+     * @access protected
+     */
+    function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null)
+    {
+        $this->last_query = $query;
+        $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre'));
+        if ($result) {
+            if (PEAR::isError($result)) {
+                return $result;
+            }
+            $query = $result;
+        }
+        if ($this->options['disable_query']) {
+            $result = $is_manip ? 0 : null;
+            return $result;
+        }
+
+        if (is_null($connection)) {
+            $connection = $this->getConnection();
+            if (PEAR::isError($connection)) {
+                return $connection;
+            }
+        }
+
+        $function = $this->options['result_buffering']
+            ? 'sqlite_query' : 'sqlite_unbuffered_query';
+        $php_errormsg = '';
+        if (version_compare('5.1.0', PHP_VERSION, '>')) {
+            @ini_set('track_errors', true);
+            do {
+                $result = @$function($query.';', $connection);
+            } while (sqlite_last_error($connection) == SQLITE_SCHEMA);
+            @ini_restore('track_errors');
+        } else {
+            do {
+                $result = @$function($query.';', $connection, SQLITE_BOTH, $php_errormsg);
+            } while (sqlite_last_error($connection) == SQLITE_SCHEMA);
+        }
+        $this->_lasterror = $php_errormsg;
+
+        if (!$result) {
+            $err =& $this->raiseError(null, null, null,
+                'Could not execute statement', __FUNCTION__);
+            return $err;
+        }
+
+        $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'post', 'result' => $result));
+        return $result;
+    }
+
+    // }}}
+    // {{{ _affectedRows()
+
+    /**
+     * Returns the number of rows affected
+     *
+     * @param resource $result
+     * @param resource $connection
+     * @return mixed MDB2 Error Object or the number of rows affected
+     * @access private
+     */
+    function _affectedRows($connection, $result = null)
+    {
+        if (is_null($connection)) {
+            $connection = $this->getConnection();
+            if (PEAR::isError($connection)) {
+                return $connection;
+            }
+        }
+        return @sqlite_changes($connection);
+    }
+
+    // }}}
+    // {{{ _modifyQuery()
+
+    /**
+     * Changes a query string for various DBMS specific reasons
+     *
+     * @param string $query  query to modify
+     * @param boolean $is_manip  if it is a DML query
+     * @param integer $limit  limit the number of rows
+     * @param integer $offset  start reading from given offset
+     * @return string modified query
+     * @access protected
+     */
+    function _modifyQuery($query, $is_manip, $limit, $offset)
+    {
+        if ($this->options['portability'] & MDB2_PORTABILITY_DELETE_COUNT) {
+            if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
+                $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
+                                      'DELETE FROM \1 WHERE 1=1', $query);
+            }
+        }
+        if ($limit > 0
+            && !preg_match('/LIMIT\s*\d(?:\s*(?:,|OFFSET)\s*\d+)?(?:[^\)]*)?$/i', $query)
+        ) {
+            $query = rtrim($query);
+            if (substr($query, -1) == ';') {
+                $query = substr($query, 0, -1);
+            }
+            if ($is_manip) {
+                $query.= " LIMIT $limit";
+            } else {
+                $query.= " LIMIT $offset,$limit";
+            }
+        }
+        return $query;
+    }
+
+    // }}}
+    // {{{ getServerVersion()
+
+    /**
+     * return version information about the server
+     *
+     * @param bool   $native  determines if the raw version string should be returned
+     * @return mixed array/string with version information or MDB2 error object
+     * @access public
+     */
+    function getServerVersion($native = false)
+    {
+        $server_info = false;
+        if ($this->connected_server_info) {
+            $server_info = $this->connected_server_info;
+        } elseif ($this->options['server_version']) {
+            $server_info = $this->options['server_version'];
+        } elseif (function_exists('sqlite_libversion')) {
+            $server_info = @sqlite_libversion();
+        }
+        if (!$server_info) {
+            return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'Requires either the "server_version" option or the sqlite_libversion() function', __FUNCTION__);
+        }
+        // cache server_info
+        $this->connected_server_info = $server_info;
+        if (!$native) {
+            $tmp = explode('.', $server_info, 3);
+            $server_info = array(
+                'major' => isset($tmp[0]) ? $tmp[0] : null,
+                'minor' => isset($tmp[1]) ? $tmp[1] : null,
+                'patch' => isset($tmp[2]) ? $tmp[2] : null,
+                'extra' => null,
+                'native' => $server_info,
+            );
+        }
+        return $server_info;
+    }
+
+    // }}}
+    // {{{ replace()
+
+    /**
+     * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
+     * query, except that if there is already a row in the table with the same
+     * key field values, the REPLACE query just updates its values instead of
+     * inserting a new row.
+     *
+     * The REPLACE type of query does not make part of the SQL standards. Since
+     * practically only SQLite implements it natively, this type of query is
+     * emulated through this method for other DBMS using standard types of
+     * queries inside a transaction to assure the atomicity of the operation.
+     *
+     * @access public
+     *
+     * @param string $table name of the table on which the REPLACE query will
+     *  be executed.
+     * @param array $fields associative array that describes the fields and the
+     *  values that will be inserted or updated in the specified table. The
+     *  indexes of the array are the names of all the fields of the table. The
+     *  values of the array are also associative arrays that describe the
+     *  values and other properties of the table fields.
+     *
+     *  Here follows a list of field properties that need to be specified:
+     *
+     *    value:
+     *          Value to be assigned to the specified field. This value may be
+     *          of specified in database independent type format as this
+     *          function can perform the necessary datatype conversions.
+     *
+     *    Default:
+     *          this property is required unless the Null property
+     *          is set to 1.
+     *
+     *    type
+     *          Name of the type of the field. Currently, all types Metabase
+     *          are supported except for clob and blob.
+     *
+     *    Default: no type conversion
+     *
+     *    null
+     *          Boolean property that indicates that the value for this field
+     *          should be set to null.
+     *
+     *          The default value for fields missing in INSERT queries may be
+     *          specified the definition of a table. Often, the default value
+     *          is already null, but since the REPLACE may be emulated using
+     *          an UPDATE query, make sure that all fields of the table are
+     *          listed in this function argument array.
+     *
+     *    Default: 0
+     *
+     *    key
+     *          Boolean property that indicates that this field should be
+     *          handled as a primary key or at least as part of the compound
+     *          unique index of the table that will determine the row that will
+     *          updated if it exists or inserted a new row otherwise.
+     *
+     *          This function will fail if no key field is specified or if the
+     *          value of a key field is set to null because fields that are
+     *          part of unique index they may not be null.
+     *
+     *    Default: 0
+     *
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     */
+    function replace($table, $fields)
+    {
+        $count = count($fields);
+        $query = $values = '';
+        $keys = $colnum = 0;
+        for (reset($fields); $colnum < $count; next($fields), $colnum++) {
+            $name = key($fields);
+            if ($colnum > 0) {
+                $query .= ',';
+                $values.= ',';
+            }
+            $query.= $name;
+            if (isset($fields[$name]['null']) && $fields[$name]['null']) {
+                $value = 'NULL';
+            } else {
+                $type = isset($fields[$name]['type']) ? $fields[$name]['type'] : null;
+                $value = $this->quote($fields[$name]['value'], $type);
+            }
+            $values.= $value;
+            if (isset($fields[$name]['key']) && $fields[$name]['key']) {
+                if ($value === 'NULL') {
+                    return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null,
+                        'key value '.$name.' may not be NULL', __FUNCTION__);
+                }
+                $keys++;
+            }
+        }
+        if ($keys == 0) {
+            return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null,
+                'not specified which fields are keys', __FUNCTION__);
+        }
+
+        $connection = $this->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+
+        $query = "REPLACE INTO $table ($query) VALUES ($values)";
+        $result =& $this->_doQuery($query, true, $connection);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        return $this->_affectedRows($connection, $result);
+    }
+
+    // }}}
+    // {{{ nextID()
+
+    /**
+     * Returns the next free id of a sequence
+     *
+     * @param string $seq_name name of the sequence
+     * @param boolean $ondemand when true the sequence is
+     *                          automatic created, if it
+     *                          not exists
+     *
+     * @return mixed MDB2 Error Object or id
+     * @access public
+     */
+    function nextID($seq_name, $ondemand = true)
+    {
+        $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
+        $seqcol_name = $this->options['seqcol_name'];
+        $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)";
+        $this->expectError(MDB2_ERROR_NOSUCHTABLE);
+        $result =& $this->_doQuery($query, true);
+        $this->popExpect();
+        if (PEAR::isError($result)) {
+            if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) {
+                $this->loadModule('Manager', null, true);
+                $result = $this->manager->createSequence($seq_name);
+                if (PEAR::isError($result)) {
+                    return $this->raiseError($result, null, null,
+                        'on demand sequence '.$seq_name.' could not be created', __FUNCTION__);
+                } else {
+                    return $this->nextID($seq_name, false);
+                }
+            }
+            return $result;
+        }
+        $value = $this->lastInsertID();
+        if (is_numeric($value)) {
+            $query = "DELETE FROM $sequence_name WHERE $seqcol_name < $value";
+            $result =& $this->_doQuery($query, true);
+            if (PEAR::isError($result)) {
+                $this->warnings[] = 'nextID: could not delete previous sequence table values from '.$seq_name;
+            }
+        }
+        return $value;
+    }
+
+    // }}}
+    // {{{ lastInsertID()
+
+    /**
+     * Returns the autoincrement ID if supported or $id or fetches the current
+     * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
+     *
+     * @param string $table name of the table into which a new row was inserted
+     * @param string $field name of the field into which a new row was inserted
+     * @return mixed MDB2 Error Object or id
+     * @access public
+     */
+    function lastInsertID($table = null, $field = null)
+    {
+        $connection = $this->getConnection();
+        if (PEAR::isError($connection)) {
+            return $connection;
+        }
+        $value = @sqlite_last_insert_rowid($connection);
+        if (!$value) {
+            return $this->raiseError(null, null, null,
+                'Could not get last insert ID', __FUNCTION__);
+        }
+        return $value;
+    }
+
+    // }}}
+    // {{{ currID()
+
+    /**
+     * Returns the current id of a sequence
+     *
+     * @param string $seq_name name of the sequence
+     * @return mixed MDB2 Error Object or id
+     * @access public
+     */
+    function currID($seq_name)
+    {
+        $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
+        $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true);
+        $query = "SELECT MAX($seqcol_name) FROM $sequence_name";
+        return $this->queryOne($query, 'integer');
+    }
+}
+
+/**
+ * MDB2 SQLite result driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Result_sqlite extends MDB2_Result_Common
+{
+    // }}}
+    // {{{ fetchRow()
+
+    /**
+     * Fetch a row and insert the data into an existing array.
+     *
+     * @param int       $fetchmode  how the array data should be indexed
+     * @param int    $rownum    number of the row where the data can be found
+     * @return int data array on success, a MDB2 error on failure
+     * @access public
+     */
+    function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)
+    {
+        if (!is_null($rownum)) {
+            $seek = $this->seek($rownum);
+            if (PEAR::isError($seek)) {
+                return $seek;
+            }
+        }
+        if ($fetchmode == MDB2_FETCHMODE_DEFAULT) {
+            $fetchmode = $this->db->fetchmode;
+        }
+        if ($fetchmode & MDB2_FETCHMODE_ASSOC) {
+            $row = @sqlite_fetch_array($this->result, SQLITE_ASSOC);
+            if (is_array($row)
+                && $this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE
+            ) {
+                $row = array_change_key_case($row, $this->db->options['field_case']);
+            }
+        } else {
+           $row = @sqlite_fetch_array($this->result, SQLITE_NUM);
+        }
+        if (!$row) {
+            if ($this->result === false) {
+                $err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                    'resultset has already been freed', __FUNCTION__);
+                return $err;
+            }
+            $null = null;
+            return $null;
+        }
+        $mode = $this->db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL;
+        $rtrim = false;
+        if ($this->db->options['portability'] & MDB2_PORTABILITY_RTRIM) {
+            if (empty($this->types)) {
+                $mode += MDB2_PORTABILITY_RTRIM;
+            } else {
+                $rtrim = true;
+            }
+        }
+        if ($mode) {
+            $this->db->_fixResultArrayValues($row, $mode);
+        }
+        if (!empty($this->types)) {
+            $row = $this->db->datatype->convertResultRow($this->types, $row, $rtrim);
+        }
+        if (!empty($this->values)) {
+            $this->_assignBindColumns($row);
+        }
+        if ($fetchmode === MDB2_FETCHMODE_OBJECT) {
+            $object_class = $this->db->options['fetch_class'];
+            if ($object_class == 'stdClass') {
+                $row = (object) $row;
+            } else {
+                $row = &new $object_class($row);
+            }
+        }
+        ++$this->rownum;
+        return $row;
+    }
+
+    // }}}
+    // {{{ _getColumnNames()
+
+    /**
+     * Retrieve the names of columns returned by the DBMS in a query result.
+     *
+     * @return  mixed   Array variable that holds the names of columns as keys
+     *                  or an MDB2 error on failure.
+     *                  Some DBMS may not return any columns when the result set
+     *                  does not contain any rows.
+     * @access private
+     */
+    function _getColumnNames()
+    {
+        $columns = array();
+        $numcols = $this->numCols();
+        if (PEAR::isError($numcols)) {
+            return $numcols;
+        }
+        for ($column = 0; $column < $numcols; $column++) {
+            $column_name = @sqlite_field_name($this->result, $column);
+            $columns[$column_name] = $column;
+        }
+        if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
+            $columns = array_change_key_case($columns, $this->db->options['field_case']);
+        }
+        return $columns;
+    }
+
+    // }}}
+    // {{{ numCols()
+
+    /**
+     * Count the number of columns returned by the DBMS in a query result.
+     *
+     * @access public
+     * @return mixed integer value with the number of columns, a MDB2 error
+     *                       on failure
+     */
+    function numCols()
+    {
+        $cols = @sqlite_num_fields($this->result);
+        if (is_null($cols)) {
+            if ($this->result === false) {
+                return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                    'resultset has already been freed', __FUNCTION__);
+            } elseif (is_null($this->result)) {
+                return count($this->types);
+            }
+            return $this->db->raiseError(null, null, null,
+                'Could not get column count', __FUNCTION__);
+        }
+        return $cols;
+    }
+}
+
+/**
+ * MDB2 SQLite buffered result driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_BufferedResult_sqlite extends MDB2_Result_sqlite
+{
+    // {{{ seek()
+
+    /**
+     * Seek to a specific row in a result set
+     *
+     * @param int    $rownum    number of the row where the data can be found
+     * @return mixed MDB2_OK on success, a MDB2 error on failure
+     * @access public
+     */
+    function seek($rownum = 0)
+    {
+        if (!@sqlite_seek($this->result, $rownum)) {
+            if ($this->result === false) {
+                return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                    'resultset has already been freed', __FUNCTION__);
+            } elseif (is_null($this->result)) {
+                return MDB2_OK;
+            }
+            return $this->db->raiseError(MDB2_ERROR_INVALID, null, null,
+                'tried to seek to an invalid row number ('.$rownum.')', __FUNCTION__);
+        }
+        $this->rownum = $rownum - 1;
+        return MDB2_OK;
+    }
+
+    // }}}
+    // {{{ valid()
+
+    /**
+     * Check if the end of the result set has been reached
+     *
+     * @return mixed true or false on sucess, a MDB2 error on failure
+     * @access public
+     */
+    function valid()
+    {
+        $numrows = $this->numRows();
+        if (PEAR::isError($numrows)) {
+            return $numrows;
+        }
+        return $this->rownum < ($numrows - 1);
+    }
+
+    // }}}
+    // {{{ numRows()
+
+    /**
+     * Returns the number of rows in a result object
+     *
+     * @return mixed MDB2 Error Object or the number of rows
+     * @access public
+     */
+    function numRows()
+    {
+        $rows = @sqlite_num_rows($this->result);
+        if (is_null($rows)) {
+            if ($this->result === false) {
+                return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                    'resultset has already been freed', __FUNCTION__);
+            } elseif (is_null($this->result)) {
+                return 0;
+            }
+            return $this->db->raiseError(null, null, null,
+                'Could not get row count', __FUNCTION__);
+        }
+        return $rows;
+    }
+}
+
+/**
+ * MDB2 SQLite statement driver
+ *
+ * @package MDB2
+ * @category Database
+ * @author  Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Statement_sqlite extends MDB2_Statement_Common
+{
+
+}
+
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Extended.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Extended.php
new file mode 100644 (file)
index 0000000..d52a141
--- /dev/null
@@ -0,0 +1,714 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP versions 4 and 5                                                 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: Extended.php,v 1.58 2007/01/06 21:40:52 quipo Exp $
+
+/**
+ * @package  MDB2
+ * @category Database
+ * @author   Lukas Smith <smith@pooteeweet.org>
+ */
+
+/**
+ * Used by autoPrepare()
+ */
+define('MDB2_AUTOQUERY_INSERT', 1);
+define('MDB2_AUTOQUERY_UPDATE', 2);
+define('MDB2_AUTOQUERY_DELETE', 3);
+define('MDB2_AUTOQUERY_SELECT', 4);
+
+/**
+ * MDB2_Extended: class which adds several high level methods to MDB2
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Extended extends MDB2_Module_Common
+{
+    // {{{ autoPrepare()
+
+    /**
+     * Generate an insert, update or delete query and call prepare() on it
+     *
+     * @param string table
+     * @param array the fields names
+     * @param int type of query to build
+     *                          MDB2_AUTOQUERY_INSERT
+     *                          MDB2_AUTOQUERY_UPDATE
+     *                          MDB2_AUTOQUERY_DELETE
+     *                          MDB2_AUTOQUERY_SELECT
+     * @param string (in case of update and delete queries, this string will be put after the sql WHERE statement)
+     * @param array that contains the types of the placeholders
+     * @param mixed array that contains the types of the columns in
+     *                        the result set or MDB2_PREPARE_RESULT, if set to
+     *                        MDB2_PREPARE_MANIP the query is handled as a manipulation query
+     *
+     * @return resource handle for the query
+     * @see buildManipSQL
+     * @access public
+     */
+    function autoPrepare($table, $table_fields, $mode = MDB2_AUTOQUERY_INSERT,
+        $where = false, $types = null, $result_types = MDB2_PREPARE_MANIP)
+    {
+        $query = $this->buildManipSQL($table, $table_fields, $mode, $where);
+        if (PEAR::isError($query)) {
+            return $query;
+        }
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+        return $db->prepare($query, $types, $result_types);
+    }
+    // }}}
+
+    // {{{ autoExecute()
+
+    /**
+     * Generate an insert, update or delete query and call prepare() and execute() on it
+     *
+     * @param string name of the table
+     * @param array assoc ($key=>$value) where $key is a field name and $value its value
+     * @param int type of query to build
+     *                          MDB2_AUTOQUERY_INSERT
+     *                          MDB2_AUTOQUERY_UPDATE
+     *                          MDB2_AUTOQUERY_DELETE
+     *                          MDB2_AUTOQUERY_SELECT
+     * @param string (in case of update and delete queries, this string will be put after the sql WHERE statement)
+     * @param array that contains the types of the placeholders
+     * @param string which specifies which result class to use
+     * @param mixed  array that contains the types of the columns in
+     *                        the result set or MDB2_PREPARE_RESULT, if set to
+     *                        MDB2_PREPARE_MANIP the query is handled as a manipulation query
+     *
+     * @return bool|MDB2_Error true on success, a MDB2 error on failure
+     * @see buildManipSQL
+     * @see autoPrepare
+     * @access public
+    */
+    function &autoExecute($table, $fields_values, $mode = MDB2_AUTOQUERY_INSERT,
+        $where = false, $types = null, $result_class = true, $result_types = MDB2_PREPARE_MANIP)
+    {
+        $fields_values = (array)$fields_values;
+        if ($mode == MDB2_AUTOQUERY_SELECT) {
+            if (is_array($result_types)) {
+                $keys = array_keys($result_types);
+            } elseif (!empty($fields_values)) {
+                $keys = $fields_values;
+            } else {
+                $keys = array();
+            }
+        } else {
+            $keys = array_keys($fields_values);
+        }
+        $params = array_values($fields_values);
+        if (empty($params)) {
+            $query = $this->buildManipSQL($table, $keys, $mode, $where);
+
+            $db =& $this->getDBInstance();
+            if (PEAR::isError($db)) {
+                return $db;
+            }
+            if ($mode == MDB2_AUTOQUERY_SELECT) {
+                $result =& $db->query($query, $result_types, $result_class);
+            } else {
+                $result = $db->exec($query);
+            }
+        } else {
+            $stmt = $this->autoPrepare($table, $keys, $mode, $where, $types, $result_types);
+            if (PEAR::isError($stmt)) {
+                return $stmt;
+            }
+            $result =& $stmt->execute($params, $result_class);
+            $stmt->free();
+        }
+        return $result;
+    }
+    // }}}
+
+    // {{{ buildManipSQL()
+
+    /**
+     * Make automaticaly an sql query for prepare()
+     *
+     * Example : buildManipSQL('table_sql', array('field1', 'field2', 'field3'), MDB2_AUTOQUERY_INSERT)
+     *           will return the string : INSERT INTO table_sql (field1,field2,field3) VALUES (?,?,?)
+     * NB : - This belongs more to a SQL Builder class, but this is a simple facility
+     *      - Be carefull ! If you don't give a $where param with an UPDATE/DELETE query, all
+     *        the records of the table will be updated/deleted !
+     *
+     * @param string name of the table
+     * @param ordered array containing the fields names
+     * @param int type of query to build
+     *                          MDB2_AUTOQUERY_INSERT
+     *                          MDB2_AUTOQUERY_UPDATE
+     *                          MDB2_AUTOQUERY_DELETE
+     *                          MDB2_AUTOQUERY_SELECT
+     * @param string (in case of update and delete queries, this string will be put after the sql WHERE statement)
+     *
+     * @return string sql query for prepare()
+     * @access public
+     */
+    function buildManipSQL($table, $table_fields, $mode, $where = false)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        if ($db->options['quote_identifier']) {
+            $table = $db->quoteIdentifier($table);
+        }
+
+        if (!empty($table_fields) && $db->options['quote_identifier']) {
+            foreach ($table_fields as $key => $field) {
+                $table_fields[$key] = $db->quoteIdentifier($field);
+            }
+        }
+
+        if ($where !== false && !is_null($where)) {
+            if (is_array($where)) {
+                $where = implode(' AND ', $where);
+            }
+            $where = ' WHERE '.$where;
+        }
+
+        switch ($mode) {
+        case MDB2_AUTOQUERY_INSERT:
+            if (empty($table_fields)) {
+                return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                'Insert requires table fields', __FUNCTION__);
+            }
+            $cols = implode(', ', $table_fields);
+            $values = '?'.str_repeat(', ?', (count($table_fields) - 1));
+            return 'INSERT INTO '.$table.' ('.$cols.') VALUES ('.$values.')';
+            break;
+        case MDB2_AUTOQUERY_UPDATE:
+            if (empty($table_fields)) {
+                return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
+                'Update requires table fields', __FUNCTION__);
+            }
+            $set = implode(' = ?, ', $table_fields).' = ?';
+            $sql = 'UPDATE '.$table.' SET '.$set.$where;
+            return $sql;
+            break;
+        case MDB2_AUTOQUERY_DELETE:
+            $sql = 'DELETE FROM '.$table.$where;
+            return $sql;
+            break;
+        case MDB2_AUTOQUERY_SELECT:
+            $cols = !empty($table_fields) ? implode(', ', $table_fields) : '*';
+            $sql = 'SELECT '.$cols.' FROM '.$table.$where;
+            return $sql;
+            break;
+        }
+        return $db->raiseError(MDB2_ERROR_SYNTAX, null, null,
+                'Non existant mode', __FUNCTION__);
+    }
+    // }}}
+
+    // {{{ limitQuery()
+
+    /**
+     * Generates a limited query
+     *
+     * @param string query
+     * @param array that contains the types of the columns in the result set
+     * @param integer the numbers of rows to fetch
+     * @param integer the row to start to fetching
+     * @param string which specifies which result class to use
+     * @param mixed   string which specifies which class to wrap results in
+     *
+     * @return MDB2_Result|MDB2_Error result set on success, a MDB2 error on failure
+     * @access public
+     */
+    function &limitQuery($query, $types, $limit, $offset = 0, $result_class = true,
+        $result_wrap_class = false)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        $result = $db->setLimit($limit, $offset);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+        $result =& $db->query($query, $types, $result_class, $result_wrap_class);
+        return $result;
+    }
+    // }}}
+
+    // {{{ execParam()
+
+    /**
+     * Execute a parameterized DML statement.
+     *
+     * @param string the SQL query
+     * @param array if supplied, prepare/execute will be used
+     *       with this array as execute parameters
+     * @param array that contains the types of the values defined in $params
+     *
+     * @return int|MDB2_Error affected rows on success, a MDB2 error on failure
+     * @access public
+     */
+    function execParam($query, $params = array(), $param_types = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        settype($params, 'array');
+        if (empty($params)) {
+            return $db->exec($query);
+        }
+
+        $stmt = $db->prepare($query, $param_types, MDB2_PREPARE_MANIP);
+        if (PEAR::isError($stmt)) {
+            return $stmt;
+        }
+
+        $result = $stmt->execute($params);
+        if (PEAR::isError($result)) {
+            return $result;
+        }
+
+        $stmt->free();
+        return $result;
+    }
+    // }}}
+
+    // {{{ getOne()
+
+    /**
+     * Fetch the first column of the first row of data returned from a query.
+     * Takes care of doing the query and freeing the results when finished.
+     *
+     * @param string the SQL query
+     * @param string that contains the type of the column in the result set
+     * @param array if supplied, prepare/execute will be used
+     *       with this array as execute parameters
+     * @param array that contains the types of the values defined in $params
+     * @param int|string which column to return
+     *
+     * @return scalar|MDB2_Error data on success, a MDB2 error on failure
+     * @access public
+     */
+    function getOne($query, $type = null, $params = array(),
+        $param_types = null, $colnum = 0)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        settype($params, 'array');
+        settype($type, 'array');
+        if (empty($params)) {
+            return $db->queryOne($query, $type, $colnum);
+        }
+
+        $stmt = $db->prepare($query, $param_types, $type);
+        if (PEAR::isError($stmt)) {
+            return $stmt;
+        }
+
+        $result = $stmt->execute($params);
+        if (!MDB2::isResultCommon($result)) {
+            return $result;
+        }
+
+        $one = $result->fetchOne($colnum);
+        $stmt->free();
+        $result->free();
+        return $one;
+    }
+    // }}}
+
+    // {{{ getRow()
+
+    /**
+     * Fetch the first row of data returned from a query.  Takes care
+     * of doing the query and freeing the results when finished.
+     *
+     * @param string the SQL query
+     * @param array that contains the types of the columns in the result set
+     * @param array if supplied, prepare/execute will be used
+     *       with this array as execute parameters
+     * @param array that contains the types of the values defined in $params
+     * @param int the fetch mode to use
+     *
+     * @return array|MDB2_Error data on success, a MDB2 error on failure
+     * @access public
+     */
+    function getRow($query, $types = null, $params = array(),
+        $param_types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        settype($params, 'array');
+        if (empty($params)) {
+            return $db->queryRow($query, $types, $fetchmode);
+        }
+
+        $stmt = $db->prepare($query, $param_types, $types);
+        if (PEAR::isError($stmt)) {
+            return $stmt;
+        }
+
+        $result = $stmt->execute($params);
+        if (!MDB2::isResultCommon($result)) {
+            return $result;
+        }
+
+        $row = $result->fetchRow($fetchmode);
+        $stmt->free();
+        $result->free();
+        return $row;
+    }
+    // }}}
+
+    // {{{ getCol()
+
+    /**
+     * Fetch a single column from a result set and return it as an
+     * indexed array.
+     *
+     * @param string the SQL query
+     * @param string that contains the type of the column in the result set
+     * @param array if supplied, prepare/execute will be used
+     *       with this array as execute parameters
+     * @param array that contains the types of the values defined in $params
+     * @param int|string which column to return
+     *
+     * @return array|MDB2_Error data on success, a MDB2 error on failure
+     * @access public
+     */
+    function getCol($query, $type = null, $params = array(),
+        $param_types = null, $colnum = 0)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        settype($params, 'array');
+        settype($type, 'array');
+        if (empty($params)) {
+            return $db->queryCol($query, $type, $colnum);
+        }
+
+        $stmt = $db->prepare($query, $param_types, $type);
+        if (PEAR::isError($stmt)) {
+            return $stmt;
+        }
+
+        $result = $stmt->execute($params);
+        if (!MDB2::isResultCommon($result)) {
+            return $result;
+        }
+
+        $col = $result->fetchCol($colnum);
+        $stmt->free();
+        $result->free();
+        return $col;
+    }
+    // }}}
+
+    // {{{ getAll()
+
+    /**
+     * Fetch all the rows returned from a query.
+     *
+     * @param string the SQL query
+     * @param array that contains the types of the columns in the result set
+     * @param array if supplied, prepare/execute will be used
+     *       with this array as execute parameters
+     * @param array that contains the types of the values defined in $params
+     * @param int the fetch mode to use
+     * @param bool if set to true, the $all will have the first
+     *       column as its first dimension
+     * @param bool $force_array used only when the query returns exactly
+     *       two columns. If true, the values of the returned array will be
+     *       one-element arrays instead of scalars.
+     * @param bool $group if true, the values of the returned array is
+     *       wrapped in another array.  If the same key value (in the first
+     *       column) repeats itself, the values will be appended to this array
+     *       instead of overwriting the existing values.
+     *
+     * @return array|MDB2_Error data on success, a MDB2 error on failure
+     * @access public
+     */
+    function getAll($query, $types = null, $params = array(),
+        $param_types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT,
+        $rekey = false, $force_array = false, $group = false)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        settype($params, 'array');
+        if (empty($params)) {
+            return $db->queryAll($query, $types, $fetchmode, $rekey, $force_array, $group);
+        }
+
+        $stmt = $db->prepare($query, $param_types, $types);
+        if (PEAR::isError($stmt)) {
+            return $stmt;
+        }
+
+        $result = $stmt->execute($params);
+        if (!MDB2::isResultCommon($result)) {
+            return $result;
+        }
+
+        $all = $result->fetchAll($fetchmode, $rekey, $force_array, $group);
+        $stmt->free();
+        $result->free();
+        return $all;
+    }
+    // }}}
+
+    // {{{ getAssoc()
+
+    /**
+     * Fetch the entire result set of a query and return it as an
+     * associative array using the first column as the key.
+     *
+     * If the result set contains more than two columns, the value
+     * will be an array of the values from column 2-n.  If the result
+     * set contains only two columns, the returned value will be a
+     * scalar with the value of the second column (unless forced to an
+     * array with the $force_array parameter).  A MDB2 error code is
+     * returned on errors.  If the result set contains fewer than two
+     * columns, a MDB2_ERROR_TRUNCATED error is returned.
+     *
+     * For example, if the table 'mytable' contains:
+     * <pre>
+     *   ID      TEXT       DATE
+     * --------------------------------
+     *   1       'one'      944679408
+     *   2       'two'      944679408
+     *   3       'three'    944679408
+     * </pre>
+     * Then the call getAssoc('SELECT id,text FROM mytable') returns:
+     * <pre>
+     *    array(
+     *      '1' => 'one',
+     *      '2' => 'two',
+     *      '3' => 'three',
+     *    )
+     * </pre>
+     * ...while the call getAssoc('SELECT id,text,date FROM mytable') returns:
+     * <pre>
+     *    array(
+     *      '1' => array('one', '944679408'),
+     *      '2' => array('two', '944679408'),
+     *      '3' => array('three', '944679408')
+     *    )
+     * </pre>
+     *
+     * If the more than one row occurs with the same value in the
+     * first column, the last row overwrites all previous ones by
+     * default.  Use the $group parameter if you don't want to
+     * overwrite like this.  Example:
+     * <pre>
+     * getAssoc('SELECT category,id,name FROM mytable', null, null
+     *           MDB2_FETCHMODE_ASSOC, false, true) returns:
+     *    array(
+     *      '1' => array(array('id' => '4', 'name' => 'number four'),
+     *                   array('id' => '6', 'name' => 'number six')
+     *             ),
+     *      '9' => array(array('id' => '4', 'name' => 'number four'),
+     *                   array('id' => '6', 'name' => 'number six')
+     *             )
+     *    )
+     * </pre>
+     *
+     * Keep in mind that database functions in PHP usually return string
+     * values for results regardless of the database's internal type.
+     *
+     * @param string the SQL query
+     * @param array that contains the types of the columns in the result set
+     * @param array if supplied, prepare/execute will be used
+     *       with this array as execute parameters
+     * @param array that contains the types of the values defined in $params
+     * @param bool $force_array used only when the query returns
+     * exactly two columns.  If TRUE, the values of the returned array
+     * will be one-element arrays instead of scalars.
+     * @param bool $group if TRUE, the values of the returned array
+     *       is wrapped in another array.  If the same key value (in the first
+     *       column) repeats itself, the values will be appended to this array
+     *       instead of overwriting the existing values.
+     *
+     * @return array|MDB2_Error data on success, a MDB2 error on failure
+     * @access public
+     */
+    function getAssoc($query, $types = null, $params = array(), $param_types = null,
+        $fetchmode = MDB2_FETCHMODE_DEFAULT, $force_array = false, $group = false)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        settype($params, 'array');
+        if (empty($params)) {
+            return $db->queryAll($query, $types, $fetchmode, true, $force_array, $group);
+        }
+
+        $stmt = $db->prepare($query, $param_types, $types);
+        if (PEAR::isError($stmt)) {
+            return $stmt;
+        }
+
+        $result = $stmt->execute($params);
+        if (!MDB2::isResultCommon($result)) {
+            return $result;
+        }
+
+        $all = $result->fetchAll($fetchmode, true, $force_array, $group);
+        $stmt->free();
+        $result->free();
+        return $all;
+    }
+    // }}}
+
+    // {{{ executeMultiple()
+
+    /**
+     * This function does several execute() calls on the same statement handle.
+     * $params must be an array indexed numerically from 0, one execute call is
+     * done for every 'row' in the array.
+     *
+     * If an error occurs during execute(), executeMultiple() does not execute
+     * the unfinished rows, but rather returns that error.
+     *
+     * @param resource query handle from prepare()
+     * @param array numeric array containing the data to insert into the query
+     *
+     * @return bool|MDB2_Error true on success, a MDB2 error on failure
+     * @access public
+     * @see prepare(), execute()
+     */
+    function executeMultiple(&$stmt, $params = null)
+    {
+        for ($i = 0, $j = count($params); $i < $j; $i++) {
+            $result = $stmt->execute($params[$i]);
+            if (PEAR::isError($result)) {
+                return $result;
+            }
+        }
+        return MDB2_OK;
+    }
+    // }}}
+
+    // {{{ getBeforeID()
+
+    /**
+     * Returns the next free id of a sequence if the RDBMS
+     * does not support auto increment
+     *
+     * @param string name of the table into which a new row was inserted
+     * @param string name of the field into which a new row was inserted
+     * @param bool when true the sequence is automatic created, if it not exists
+     * @param bool if the returned value should be quoted
+     *
+     * @return int|MDB2_Error id on success, a MDB2 error on failure
+     * @access public
+     */
+    function getBeforeID($table, $field = null, $ondemand = true, $quote = true)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        if ($db->supports('auto_increment') !== true) {
+            $seq = $table.(empty($field) ? '' : '_'.$field);
+            $id = $db->nextID($seq, $ondemand);
+            if (!$quote || PEAR::isError($id)) {
+                return $id;
+            }
+            return $db->quote($id, 'integer');
+        } elseif (!$quote) {
+            return null;
+        }
+        return 'NULL';
+    }
+    // }}}
+
+    // {{{ getAfterID()
+
+    /**
+     * Returns the autoincrement ID if supported or $id
+     *
+     * @param mixed value as returned by getBeforeId()
+     * @param string name of the table into which a new row was inserted
+     * @param string name of the field into which a new row was inserted
+     *
+     * @return int|MDB2_Error id on success, a MDB2 error on failure
+     * @access public
+     */
+    function getAfterID($id, $table, $field = null)
+    {
+        $db =& $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        if ($db->supports('auto_increment') !== true) {
+            return $id;
+        }
+        return $db->lastInsertID($table, $field);
+    }
+    // }}}
+}
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Iterator.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/Iterator.php
new file mode 100644 (file)
index 0000000..ca5e7b6
--- /dev/null
@@ -0,0 +1,259 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP version 5                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: Iterator.php,v 1.22 2006/05/06 14:03:41 lsmith Exp $
+
+/**
+ * PHP5 Iterator
+ *
+ * @package  MDB2
+ * @category Database
+ * @author   Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_Iterator implements Iterator
+{
+    protected $fetchmode;
+    protected $result;
+    protected $row;
+
+    // {{{ constructor
+
+    /**
+     * Constructor
+     */
+    public function __construct($result, $fetchmode = MDB2_FETCHMODE_DEFAULT)
+    {
+        $this->result = $result;
+        $this->fetchmode = $fetchmode;
+    }
+    // }}}
+
+    // {{{ seek()
+
+    /**
+     * Seek forward to a specific row in a result set
+     *
+     * @param int number of the row where the data can be found
+     *
+     * @return void
+     * @access public
+     */
+    public function seek($rownum)
+    {
+        $this->row = null;
+        if ($this->result) {
+            $this->result->seek($rownum);
+        }
+    }
+    // }}}
+
+    // {{{ next()
+
+    /**
+     * Fetch next row of data
+     *
+     * @return void
+     * @access public
+     */
+    public function next()
+    {
+        $this->row = null;
+    }
+    // }}}
+
+    // {{{ current()
+
+    /**
+     * return a row of data
+     *
+     * @return void
+     * @access public
+     */
+    public function current()
+    {
+        if (is_null($this->row)) {
+            $row = $this->result->fetchRow($this->fetchmode);
+            if (PEAR::isError($row)) {
+                $row = false;
+            }
+            $this->row = $row;
+        }
+        return $this->row;
+    }
+    // }}}
+
+    // {{{ valid()
+
+    /**
+     * Check if the end of the result set has been reached
+     *
+     * @return bool true/false, false is also returned on failure
+     * @access public
+     */
+    public function valid()
+    {
+        return (bool)$this->current();
+    }
+    // }}}
+
+    // {{{ free()
+
+    /**
+     * Free the internal resources associated with result.
+     *
+     * @return bool|MDB2_Error true on success, false|MDB2_Error if result is invalid
+     * @access public
+     */
+    public function free()
+    {
+        if ($this->result) {
+            return $this->result->free();
+        }
+        $this->result = false;
+        $this->row = null;
+        return false;
+    }
+    // }}}
+
+    // {{{ key()
+
+    /**
+     * Returns the row number
+     *
+     * @return int|bool|MDB2_Error true on success, false|MDB2_Error if result is invalid
+     * @access public
+     */
+    public function key()
+    {
+        if ($this->result) {
+            return $this->result->rowCount();
+        }
+        return false;
+    }
+    // }}}
+
+    // {{{ rewind()
+
+    /**
+     * Seek to the first row in a result set
+     *
+     * @return void
+     * @access public
+     */
+    public function rewind()
+    {
+    }
+    // }}}
+
+    // {{{ destructor
+
+    /**
+     * Destructor
+     */
+    public function __destruct()
+    {
+        $this->free();
+    }
+    // }}}
+}
+
+/**
+ * PHP5 buffered Iterator
+ *
+ * @package  MDB2
+ * @category Database
+ * @author   Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_BufferedIterator extends MDB2_Iterator implements SeekableIterator
+{
+    // {{{ valid()
+
+    /**
+     * Check if the end of the result set has been reached
+     *
+     * @return bool|MDB2_Error true on success, false|MDB2_Error if result is invalid
+     * @access public
+     */
+    public function valid()
+    {
+        if ($this->result) {
+            return $this->result->valid();
+        }
+        return false;
+    }
+    // }}}
+
+    // {{{count()
+
+    /**
+     * Returns the number of rows in a result object
+     *
+     * @return int|MDB2_Error number of rows, false|MDB2_Error if result is invalid
+     * @access public
+     */
+    public function count()
+    {
+        if ($this->result) {
+            return $this->result->numRows();
+        }
+        return false;
+    }
+    // }}}
+
+    // {{{ rewind()
+
+    /**
+     * Seek to the first row in a result set
+     *
+     * @return void
+     * @access public
+     */
+    public function rewind()
+    {
+        $this->seek(0);
+    }
+    // }}}
+}
+
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/LOB.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/MDB2/LOB.php
new file mode 100644 (file)
index 0000000..69db267
--- /dev/null
@@ -0,0 +1,264 @@
+<?php
+// +----------------------------------------------------------------------+
+// | PHP version 5                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Stig. S. Bakken, Lukas Smith                                         |
+// | All rights reserved.                                                 |
+// +----------------------------------------------------------------------+
+// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
+// | API as well as database abstraction for PHP applications.            |
+// | This LICENSE is in the BSD license style.                            |
+// |                                                                      |
+// | 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 Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
+// | Lukas Smith nor the names of his 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      |
+// | REGENTS 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.                                          |
+// +----------------------------------------------------------------------+
+// | Author: Lukas Smith <smith@pooteeweet.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: LOB.php,v 1.34 2006/10/25 11:52:21 lsmith Exp $
+
+/**
+ * @package  MDB2
+ * @category Database
+ * @author   Lukas Smith <smith@pooteeweet.org>
+ */
+
+require_once 'MDB2.php';
+
+/**
+ * MDB2_LOB: user land stream wrapper implementation for LOB support
+ *
+ * @package MDB2
+ * @category Database
+ * @author Lukas Smith <smith@pooteeweet.org>
+ */
+class MDB2_LOB
+{
+    /**
+     * contains the key to the global MDB2 instance array of the associated
+     * MDB2 instance
+     *
+     * @var integer
+     * @access protected
+     */
+    var $db_index;
+
+    /**
+     * contains the key to the global MDB2_LOB instance array of the associated
+     * MDB2_LOB instance
+     *
+     * @var integer
+     * @access protected
+     */
+    var $lob_index;
+
+    // {{{ stream_open()
+
+    /**
+     * open stream
+     *
+     * @param string specifies the URL that was passed to fopen()
+     * @param string the mode used to open the file
+     * @param int holds additional flags set by the streams API
+     * @param string not used
+     *
+     * @return bool
+     * @access public
+     */
+    function stream_open($path, $mode, $options, &$opened_path)
+    {
+        if (!preg_match('/^rb?\+?$/', $mode)) {
+            return false;
+        }
+        $url = parse_url($path);
+        if (empty($url['host'])) {
+            return false;
+        }
+        $this->db_index = (int)$url['host'];
+        if (!isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
+            return false;
+        }
+        $db =& $GLOBALS['_MDB2_databases'][$this->db_index];
+        $this->lob_index = (int)$url['user'];
+        if (!isset($db->datatype->lobs[$this->lob_index])) {
+            return false;
+        }
+        return true;
+    }
+    // }}}
+
+    // {{{ stream_read()
+
+    /**
+     * read stream
+     *
+     * @param int number of bytes to read
+     *
+     * @return string
+     * @access public
+     */
+    function stream_read($count)
+    {
+        if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
+            $db =& $GLOBALS['_MDB2_databases'][$this->db_index];
+            $db->datatype->_retrieveLOB($db->datatype->lobs[$this->lob_index]);
+
+            $data = $db->datatype->_readLOB($db->datatype->lobs[$this->lob_index], $count);
+            $length = strlen($data);
+            if ($length == 0) {
+                $db->datatype->lobs[$this->lob_index]['endOfLOB'] = true;
+            }
+            $db->datatype->lobs[$this->lob_index]['position'] += $length;
+            return $data;
+        }
+    }
+    // }}}
+
+    // {{{ stream_write()
+
+    /**
+     * write stream, note implemented
+     *
+     * @param string data
+     *
+     * @return int
+     * @access public
+     */
+    function stream_write($data)
+    {
+        return 0;
+    }
+    // }}}
+
+    // {{{ stream_tell()
+
+    /**
+     * return the current position
+     *
+     * @return int current position
+     * @access public
+     */
+    function stream_tell()
+    {
+        if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
+            $db =& $GLOBALS['_MDB2_databases'][$this->db_index];
+            return $db->datatype->lobs[$this->lob_index]['position'];
+        }
+    }
+    // }}}
+
+    // {{{ stream_eof()
+
+    /**
+     * Check if stream reaches EOF
+     *
+     * @return bool
+     * @access public
+     */
+    function stream_eof()
+    {
+        if (!isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
+            return true;
+        }
+
+        $db =& $GLOBALS['_MDB2_databases'][$this->db_index];
+        $result = $db->datatype->_endOfLOB($db->datatype->lobs[$this->lob_index]);
+        if (version_compare(phpversion(), "5.0", ">=")
+            && version_compare(phpversion(), "5.1", "<")
+        ) {
+            return !$result;
+        }
+        return $result;
+    }
+    // }}}
+
+    // {{{ stream_seek()
+
+    /**
+     * Seek stream, not implemented
+     *
+     * @param int offset
+     * @param int whence
+     *
+     * @return bool
+     * @access public
+     */
+    function stream_seek($offset, $whence)
+    {
+        return false;
+    }
+    // }}}
+
+    // {{{ stream_stat()
+
+    /**
+     * return information about stream
+     *
+     * @access public
+     */
+    function stream_stat()
+    {
+        if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
+            $db =& $GLOBALS['_MDB2_databases'][$this->db_index];
+            return array(
+              'db_index' => $this->db_index,
+              'lob_index' => $this->lob_index,
+            );
+        }
+    }
+    // }}}
+
+    // {{{ stream_close()
+
+    /**
+     * close stream
+     *
+     * @access public
+     */
+    function stream_close()
+    {
+        if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
+            $db =& $GLOBALS['_MDB2_databases'][$this->db_index];
+            if (isset($db->datatype->lobs[$this->lob_index])) {
+                $db->datatype->_destroyLOB($db->datatype->lobs[$this->lob_index]);
+                unset($db->datatype->lobs[$this->lob_index]);
+            }
+        }
+    }
+    // }}}
+}
+
+// register streams wrapper
+if (!stream_wrapper_register("MDB2LOB", "MDB2_LOB")) {
+    MDB2::raiseError();
+    return false;
+}
+
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/OS/Guess.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/OS/Guess.php
new file mode 100644 (file)
index 0000000..4eb6173
--- /dev/null
@@ -0,0 +1,344 @@
+<?php
+/**
+ * The OS_Guess class
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category   pear
+ * @package    PEAR
+ * @author     Stig Bakken <ssb@php.net>
+ * @author     Gregory Beaver <cellog@php.net>
+ * @copyright  1997-2005 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    CVS: $Id: Guess.php,v 1.25 2006/12/14 00:24:37 cellog Exp $
+ * @link       http://pear.php.net/package/PEAR
+ * @since      File available since PEAR 0.1
+ */
+
+// {{{ uname examples
+
+// php_uname() without args returns the same as 'uname -a', or a PHP-custom
+// string for Windows.
+// PHP versions prior to 4.3 return the uname of the host where PHP was built,
+// as of 4.3 it returns the uname of the host running the PHP code.
+//
+// PC RedHat Linux 7.1:
+// Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown
+//
+// PC Debian Potato:
+// Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown
+//
+// PC FreeBSD 3.3:
+// FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000     root@example.com:/usr/src/sys/compile/CONFIG  i386
+//
+// PC FreeBSD 4.3:
+// FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001     root@example.com:/usr/src/sys/compile/CONFIG  i386
+//
+// PC FreeBSD 4.5:
+// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb  6 23:59:23 CET 2002     root@example.com:/usr/src/sys/compile/CONFIG  i386
+//
+// PC FreeBSD 4.5 w/uname from GNU shellutils:
+// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb  i386 unknown
+//
+// HP 9000/712 HP-UX 10:
+// HP-UX iq B.10.10 A 9000/712 2008429113 two-user license
+//
+// HP 9000/712 HP-UX 10 w/uname from GNU shellutils:
+// HP-UX host B.10.10 A 9000/712 unknown
+//
+// IBM RS6000/550 AIX 4.3:
+// AIX host 3 4 000003531C00
+//
+// AIX 4.3 w/uname from GNU shellutils:
+// AIX host 3 4 000003531C00 unknown
+//
+// SGI Onyx IRIX 6.5 w/uname from GNU shellutils:
+// IRIX64 host 6.5 01091820 IP19 mips
+//
+// SGI Onyx IRIX 6.5:
+// IRIX64 host 6.5 01091820 IP19
+//
+// SparcStation 20 Solaris 8 w/uname from GNU shellutils:
+// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc
+//
+// SparcStation 20 Solaris 8:
+// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20
+//
+// Mac OS X (Darwin)
+// Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug  5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC  Power Macintosh
+//
+// Mac OS X early versions
+// 
+
+// }}}
+
+/* TODO:
+ * - define endianness, to allow matchSignature("bigend") etc.
+ */
+
+/**
+ * Retrieves information about the current operating system
+ *
+ * This class uses php_uname() to grok information about the current OS
+ *
+ * @category   pear
+ * @package    PEAR
+ * @author     Stig Bakken <ssb@php.net>
+ * @author     Gregory Beaver <cellog@php.net>
+ * @copyright  1997-2005 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    Release: 1.6.1
+ * @link       http://pear.php.net/package/PEAR
+ * @since      Class available since Release 0.1
+ */
+class OS_Guess
+{
+    var $sysname;
+    var $nodename;
+    var $cpu;
+    var $release;
+    var $extra;
+
+    function OS_Guess($uname = null)
+    {
+        list($this->sysname,
+             $this->release,
+             $this->cpu,
+             $this->extra,
+             $this->nodename) = $this->parseSignature($uname);
+    }
+
+    function parseSignature($uname = null)
+    {
+        static $sysmap = array(
+            'HP-UX' => 'hpux',
+            'IRIX64' => 'irix',
+        );
+        static $cpumap = array(
+            'i586' => 'i386',
+            'i686' => 'i386',
+            'ppc' => 'powerpc',
+        );
+        if ($uname === null) {
+            $uname = php_uname();
+        }
+        $parts = split('[[:space:]]+', trim($uname));
+        $n = count($parts);
+
+        $release = $machine = $cpu = '';
+        $sysname = $parts[0];
+        $nodename = $parts[1];
+        $cpu = $parts[$n-1];
+        $extra = '';
+        if ($cpu == 'unknown') {
+            $cpu = $parts[$n-2];
+        }
+
+        switch ($sysname) {
+            case 'AIX' :
+                $release = "$parts[3].$parts[2]";
+                break;
+            case 'Windows' :
+                switch ($parts[1]) {
+                    case '95/98':
+                        $release = '9x';
+                        break;
+                    default:
+                        $release = $parts[1];
+                        break;
+                }
+                $cpu = 'i386';
+                break;
+            case 'Linux' :
+                $extra = $this->_detectGlibcVersion();
+                // use only the first two digits from the kernel version
+                $release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]);
+                break;
+            case 'Mac' :
+                $sysname = 'darwin';
+                $nodename = $parts[2];
+                $release = $parts[3];
+                if ($cpu == 'Macintosh') {
+                    if ($parts[$n - 2] == 'Power') {
+                        $cpu = 'powerpc';
+                    }
+                }
+                break;
+            case 'Darwin' :
+                if ($cpu == 'Macintosh') {
+                    if ($parts[$n - 2] == 'Power') {
+                        $cpu = 'powerpc';
+                    }
+                }
+                $release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]);
+                break;
+            default:
+                $release = ereg_replace('-.*', '', $parts[2]);
+                break;
+        }
+
+
+        if (isset($sysmap[$sysname])) {
+            $sysname = $sysmap[$sysname];
+        } else {
+            $sysname = strtolower($sysname);
+        }
+        if (isset($cpumap[$cpu])) {
+            $cpu = $cpumap[$cpu];
+        }
+        return array($sysname, $release, $cpu, $extra, $nodename);
+    }
+
+    function _detectGlibcVersion()
+    {
+        static $glibc = false;
+        if ($glibc !== false) {
+            return $glibc; // no need to run this multiple times
+        }
+        $major = $minor = 0;
+        include_once "System.php";
+        // Use glibc's <features.h> header file to
+        // get major and minor version number:
+        if (@file_exists('/usr/include/features.h') &&
+              @is_readable('/usr/include/features.h')) {
+            if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) {
+                $features_file = fopen('/usr/include/features.h', 'rb');
+                while (!feof($features_file)) {
+                    $line = fgets($features_file, 8192);
+                    if (!$line || (strpos($line, '#define') === false)) {
+                        continue;
+                    }
+                    if (strpos($line, '__GLIBC__')) {
+                        // major version number #define __GLIBC__ version
+                        $line = preg_split('/\s+/', $line);
+                        $glibc_major = trim($line[2]);
+                        if (isset($glibc_minor)) {
+                            break;
+                        }
+                        continue;
+                    }
+                    if (strpos($line, '__GLIBC_MINOR__'))  {
+                        // got the minor version number
+                        // #define __GLIBC_MINOR__ version
+                        $line = preg_split('/\s+/', $line);
+                        $glibc_minor = trim($line[2]);
+                        if (isset($glibc_major)) {
+                            break;
+                        }
+                        continue;
+                    }
+                }
+                fclose($features_file);
+                if (!isset($glibc_major) || !isset($glibc_minor)) {
+                    return $glibc = '';
+                }
+                return $glibc = 'glibc' . trim($glibc_major) . "." . trim($glibc_minor) ;
+            } // no cpp
+            $tmpfile = System::mktemp("glibctest");
+            $fp = fopen($tmpfile, "w");
+            fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n");
+            fclose($fp);
+            $cpp = popen("/usr/bin/cpp $tmpfile", "r");
+            while ($line = fgets($cpp, 1024)) {
+                if ($line{0} == '#' || trim($line) == '') {
+                    continue;
+                }
+                if (list($major, $minor) = explode(' ', trim($line))) {
+                    break;
+                }
+            }
+            pclose($cpp);
+            unlink($tmpfile);
+        } // features.h
+        if (!($major && $minor) && @is_link('/lib/libc.so.6')) {
+            // Let's try reading the libc.so.6 symlink
+            if (ereg('^libc-(.*)\.so$', basename(readlink('/lib/libc.so.6')), $matches)) {
+                list($major, $minor) = explode('.', $matches[1]);
+            }
+        }
+        if (!($major && $minor)) {
+            return $glibc = '';
+        }
+        return $glibc = "glibc{$major}.{$minor}";
+    }
+
+    function getSignature()
+    {
+        if (empty($this->extra)) {
+            return "{$this->sysname}-{$this->release}-{$this->cpu}";
+        }
+        return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}";
+    }
+
+    function getSysname()
+    {
+        return $this->sysname;
+    }
+
+    function getNodename()
+    {
+        return $this->nodename;
+    }
+
+    function getCpu()
+    {
+        return $this->cpu;
+    }
+
+    function getRelease()
+    {
+        return $this->release;
+    }
+
+    function getExtra()
+    {
+        return $this->extra;
+    }
+
+    function matchSignature($match)
+    {
+        if (is_array($match)) {
+            $fragments = $match;
+        } else {
+            $fragments = explode('-', $match);
+        }
+        $n = count($fragments);
+        $matches = 0;
+        if ($n > 0) {
+            $matches += $this->_matchFragment($fragments[0], $this->sysname);
+        }
+        if ($n > 1) {
+            $matches += $this->_matchFragment($fragments[1], $this->release);
+        }
+        if ($n > 2) {
+            $matches += $this->_matchFragment($fragments[2], $this->cpu);
+        }
+        if ($n > 3) {
+            $matches += $this->_matchFragment($fragments[3], $this->extra);
+        }
+        return ($matches == $n);
+    }
+
+    function _matchFragment($fragment, $value)
+    {
+        if (strcspn($fragment, '*?') < strlen($fragment)) {
+            $reg = '^' . str_replace(array('*', '?', '/'), array('.*', '.', '\\/'), $fragment) . '$';
+            return eregi($reg, $value);
+        }
+        return ($fragment == '*' || !strcasecmp($fragment, $value));
+    }
+
+}
+/*
+ * Local Variables:
+ * indent-tabs-mode: nil
+ * c-basic-offset: 4
+ * End:
+ */
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/PEAR.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/PEAR.php
new file mode 100644 (file)
index 0000000..fc879a0
--- /dev/null
@@ -0,0 +1,1108 @@
+<?php
+/**
+ * PEAR, the PHP Extension and Application Repository
+ *
+ * PEAR class and PEAR_Error class
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category   pear
+ * @package    PEAR
+ * @author     Sterling Hughes <sterling@php.net>
+ * @author     Stig Bakken <ssb@php.net>
+ * @author     Tomas V.V.Cox <cox@idecnet.com>
+ * @author     Greg Beaver <cellog@php.net>
+ * @copyright  1997-2006 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    CVS: $Id: PEAR.php,v 1.101 2006/04/25 02:41:03 cellog Exp $
+ * @link       http://pear.php.net/package/PEAR
+ * @since      File available since Release 0.1
+ */
+
+/**#@+
+ * ERROR constants
+ */
+define('PEAR_ERROR_RETURN',     1);
+define('PEAR_ERROR_PRINT',      2);
+define('PEAR_ERROR_TRIGGER',    4);
+define('PEAR_ERROR_DIE',        8);
+define('PEAR_ERROR_CALLBACK',  16);
+/**
+ * WARNING: obsolete
+ * @deprecated
+ */
+define('PEAR_ERROR_EXCEPTION', 32);
+/**#@-*/
+define('PEAR_ZE2', (function_exists('version_compare') &&
+                    version_compare(zend_version(), "2-dev", "ge")));
+
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+    define('OS_WINDOWS', true);
+    define('OS_UNIX',    false);
+    define('PEAR_OS',    'Windows');
+} else {
+    define('OS_WINDOWS', false);
+    define('OS_UNIX',    true);
+    define('PEAR_OS',    'Unix'); // blatant assumption
+}
+
+// instant backwards compatibility
+if (!defined('PATH_SEPARATOR')) {
+    if (OS_WINDOWS) {
+        define('PATH_SEPARATOR', ';');
+    } else {
+        define('PATH_SEPARATOR', ':');
+    }
+}
+
+$GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
+$GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
+$GLOBALS['_PEAR_destructor_object_list'] = array();
+$GLOBALS['_PEAR_shutdown_funcs']         = array();
+$GLOBALS['_PEAR_error_handler_stack']    = array();
+
+@ini_set('track_errors', true);
+
+/**
+ * Base class for other PEAR classes.  Provides rudimentary
+ * emulation of destructors.
+ *
+ * If you want a destructor in your class, inherit PEAR and make a
+ * destructor method called _yourclassname (same name as the
+ * constructor, but with a "_" prefix).  Also, in your constructor you
+ * have to call the PEAR constructor: $this->PEAR();.
+ * The destructor method will be called without parameters.  Note that
+ * at in some SAPI implementations (such as Apache), any output during
+ * the request shutdown (in which destructors are called) seems to be
+ * discarded.  If you need to get any debug information from your
+ * destructor, use error_log(), syslog() or something similar.
+ *
+ * IMPORTANT! To use the emulated destructors you need to create the
+ * objects by reference: $obj =& new PEAR_child;
+ *
+ * @category   pear
+ * @package    PEAR
+ * @author     Stig Bakken <ssb@php.net>
+ * @author     Tomas V.V. Cox <cox@idecnet.com>
+ * @author     Greg Beaver <cellog@php.net>
+ * @copyright  1997-2006 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    Release: 1.6.1
+ * @link       http://pear.php.net/package/PEAR
+ * @see        PEAR_Error
+ * @since      Class available since PHP 4.0.2
+ * @link        http://pear.php.net/manual/en/core.pear.php#core.pear.pear
+ */
+class PEAR
+{
+    // {{{ properties
+
+    /**
+     * Whether to enable internal debug messages.
+     *
+     * @var     bool
+     * @access  private
+     */
+    var $_debug = false;
+
+    /**
+     * Default error mode for this object.
+     *
+     * @var     int
+     * @access  private
+     */
+    var $_default_error_mode = null;
+
+    /**
+     * Default error options used for this object when error mode
+     * is PEAR_ERROR_TRIGGER.
+     *
+     * @var     int
+     * @access  private
+     */
+    var $_default_error_options = null;
+
+    /**
+     * Default error handler (callback) for this object, if error mode is
+     * PEAR_ERROR_CALLBACK.
+     *
+     * @var     string
+     * @access  private
+     */
+    var $_default_error_handler = '';
+
+    /**
+     * Which class to use for error objects.
+     *
+     * @var     string
+     * @access  private
+     */
+    var $_error_class = 'PEAR_Error';
+
+    /**
+     * An array of expected errors.
+     *
+     * @var     array
+     * @access  private
+     */
+    var $_expected_errors = array();
+
+    // }}}
+
+    // {{{ constructor
+
+    /**
+     * Constructor.  Registers this object in
+     * $_PEAR_destructor_object_list for destructor emulation if a
+     * destructor object exists.
+     *
+     * @param string $error_class  (optional) which class to use for
+     *        error objects, defaults to PEAR_Error.
+     * @access public
+     * @return void
+     */
+    function PEAR($error_class = null)
+    {
+        $classname = strtolower(get_class($this));
+        if ($this->_debug) {
+            print "PEAR constructor called, class=$classname\n";
+        }
+        if ($error_class !== null) {
+            $this->_error_class = $error_class;
+        }
+        while ($classname && strcasecmp($classname, "pear")) {
+            $destructor = "_$classname";
+            if (method_exists($this, $destructor)) {
+                global $_PEAR_destructor_object_list;
+                $_PEAR_destructor_object_list[] = &$this;
+                if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
+                    register_shutdown_function("_PEAR_call_destructors");
+                    $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
+                }
+                break;
+            } else {
+                $classname = get_parent_class($classname);
+            }
+        }
+    }
+
+    // }}}
+    // {{{ destructor
+
+    /**
+     * Destructor (the emulated type of...).  Does nothing right now,
+     * but is included for forward compatibility, so subclass
+     * destructors should always call it.
+     *
+     * See the note in the class desciption about output from
+     * destructors.
+     *
+     * @access public
+     * @return void
+     */
+    function _PEAR() {
+        if ($this->_debug) {
+            printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
+        }
+    }
+
+    // }}}
+    // {{{ getStaticProperty()
+
+    /**
+    * If you have a class that's mostly/entirely static, and you need static
+    * properties, you can use this method to simulate them. Eg. in your method(s)
+    * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
+    * You MUST use a reference, or they will not persist!
+    *
+    * @access public
+    * @param  string $class  The calling classname, to prevent clashes
+    * @param  string $var    The variable to retrieve.
+    * @return mixed   A reference to the variable. If not set it will be
+    *                 auto initialised to NULL.
+    */
+    function &getStaticProperty($class, $var)
+    {
+        static $properties;
+        if (!isset($properties[$class])) {
+            $properties[$class] = array();
+        }
+        if (!array_key_exists($var, $properties[$class])) {
+            $properties[$class][$var] = null;
+        }
+        return $properties[$class][$var];
+    }
+
+    // }}}
+    // {{{ registerShutdownFunc()
+
+    /**
+    * Use this function to register a shutdown method for static
+    * classes.
+    *
+    * @access public
+    * @param  mixed $func  The function name (or array of class/method) to call
+    * @param  mixed $args  The arguments to pass to the function
+    * @return void
+    */
+    function registerShutdownFunc($func, $args = array())
+    {
+        // if we are called statically, there is a potential
+        // that no shutdown func is registered.  Bug #6445
+        if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
+            register_shutdown_function("_PEAR_call_destructors");
+            $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
+        }
+        $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
+    }
+
+    // }}}
+    // {{{ isError()
+
+    /**
+     * Tell whether a value is a PEAR error.
+     *
+     * @param   mixed $data   the value to test
+     * @param   int   $code   if $data is an error object, return true
+     *                        only if $code is a string and
+     *                        $obj->getMessage() == $code or
+     *                        $code is an integer and $obj->getCode() == $code
+     * @access  public
+     * @return  bool    true if parameter is an error
+     */
+    function isError($data, $code = null)
+    {
+        if (is_a($data, 'PEAR_Error')) {
+            if (is_null($code)) {
+                return true;
+            } elseif (is_string($code)) {
+                return $data->getMessage() == $code;
+            } else {
+                return $data->getCode() == $code;
+            }
+        }
+        return false;
+    }
+
+    // }}}
+    // {{{ setErrorHandling()
+
+    /**
+     * Sets how errors generated by this object should be handled.
+     * Can be invoked both in objects and statically.  If called
+     * statically, setErrorHandling sets the default behaviour for all
+     * PEAR objects.  If called in an object, setErrorHandling sets
+     * the default behaviour for that object.
+     *
+     * @param int $mode
+     *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
+     *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
+     *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
+     *
+     * @param mixed $options
+     *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
+     *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
+     *
+     *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
+     *        to be the callback function or method.  A callback
+     *        function is a string with the name of the function, a
+     *        callback method is an array of two elements: the element
+     *        at index 0 is the object, and the element at index 1 is
+     *        the name of the method to call in the object.
+     *
+     *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
+     *        a printf format string used when printing the error
+     *        message.
+     *
+     * @access public
+     * @return void
+     * @see PEAR_ERROR_RETURN
+     * @see PEAR_ERROR_PRINT
+     * @see PEAR_ERROR_TRIGGER
+     * @see PEAR_ERROR_DIE
+     * @see PEAR_ERROR_CALLBACK
+     * @see PEAR_ERROR_EXCEPTION
+     *
+     * @since PHP 4.0.5
+     */
+
+    function setErrorHandling($mode = null, $options = null)
+    {
+        if (isset($this) && is_a($this, 'PEAR')) {
+            $setmode     = &$this->_default_error_mode;
+            $setoptions  = &$this->_default_error_options;
+        } else {
+            $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
+            $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
+        }
+
+        switch ($mode) {
+            case PEAR_ERROR_EXCEPTION:
+            case PEAR_ERROR_RETURN:
+            case PEAR_ERROR_PRINT:
+            case PEAR_ERROR_TRIGGER:
+            case PEAR_ERROR_DIE:
+            case null:
+                $setmode = $mode;
+                $setoptions = $options;
+                break;
+
+            case PEAR_ERROR_CALLBACK:
+                $setmode = $mode;
+                // class/object method callback
+                if (is_callable($options)) {
+                    $setoptions = $options;
+                } else {
+                    trigger_error("invalid error callback", E_USER_WARNING);
+                }
+                break;
+
+            default:
+                trigger_error("invalid error mode", E_USER_WARNING);
+                break;
+        }
+    }
+
+    // }}}
+    // {{{ expectError()
+
+    /**
+     * This method is used to tell which errors you expect to get.
+     * Expected errors are always returned with error mode
+     * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
+     * and this method pushes a new element onto it.  The list of
+     * expected errors are in effect until they are popped off the
+     * stack with the popExpect() method.
+     *
+     * Note that this method can not be called statically
+     *
+     * @param mixed $code a single error code or an array of error codes to expect
+     *
+     * @return int     the new depth of the "expected errors" stack
+     * @access public
+     */
+    function expectError($code = '*')
+    {
+        if (is_array($code)) {
+            array_push($this->_expected_errors, $code);
+        } else {
+            array_push($this->_expected_errors, array($code));
+        }
+        return sizeof($this->_expected_errors);
+    }
+
+    // }}}
+    // {{{ popExpect()
+
+    /**
+     * This method pops one element off the expected error codes
+     * stack.
+     *
+     * @return array   the list of error codes that were popped
+     */
+    function popExpect()
+    {
+        return array_pop($this->_expected_errors);
+    }
+
+    // }}}
+    // {{{ _checkDelExpect()
+
+    /**
+     * This method checks unsets an error code if available
+     *
+     * @param mixed error code
+     * @return bool true if the error code was unset, false otherwise
+     * @access private
+     * @since PHP 4.3.0
+     */
+    function _checkDelExpect($error_code)
+    {
+        $deleted = false;
+
+        foreach ($this->_expected_errors AS $key => $error_array) {
+            if (in_array($error_code, $error_array)) {
+                unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
+                $deleted = true;
+            }
+
+            // clean up empty arrays
+            if (0 == count($this->_expected_errors[$key])) {
+                unset($this->_expected_errors[$key]);
+            }
+        }
+        return $deleted;
+    }
+
+    // }}}
+    // {{{ delExpect()
+
+    /**
+     * This method deletes all occurences of the specified element from
+     * the expected error codes stack.
+     *
+     * @param  mixed $error_code error code that should be deleted
+     * @return mixed list of error codes that were deleted or error
+     * @access public
+     * @since PHP 4.3.0
+     */
+    function delExpect($error_code)
+    {
+        $deleted = false;
+
+        if ((is_array($error_code) && (0 != count($error_code)))) {
+            // $error_code is a non-empty array here;
+            // we walk through it trying to unset all
+            // values
+            foreach($error_code as $key => $error) {
+                if ($this->_checkDelExpect($error)) {
+                    $deleted =  true;
+                } else {
+                    $deleted = false;
+                }
+            }
+            return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
+        } elseif (!empty($error_code)) {
+            // $error_code comes alone, trying to unset it
+            if ($this->_checkDelExpect($error_code)) {
+                return true;
+            } else {
+                return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
+            }
+        } else {
+            // $error_code is empty
+            return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
+        }
+    }
+
+    // }}}
+    // {{{ raiseError()
+
+    /**
+     * This method is a wrapper that returns an instance of the
+     * configured error class with this object's default error
+     * handling applied.  If the $mode and $options parameters are not
+     * specified, the object's defaults are used.
+     *
+     * @param mixed $message a text error message or a PEAR error object
+     *
+     * @param int $code      a numeric error code (it is up to your class
+     *                  to define these if you want to use codes)
+     *
+     * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
+     *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
+     *                  PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
+     *
+     * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
+     *                  specifies the PHP-internal error level (one of
+     *                  E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
+     *                  If $mode is PEAR_ERROR_CALLBACK, this
+     *                  parameter specifies the callback function or
+     *                  method.  In other error modes this parameter
+     *                  is ignored.
+     *
+     * @param string $userinfo If you need to pass along for example debug
+     *                  information, this parameter is meant for that.
+     *
+     * @param string $error_class The returned error object will be
+     *                  instantiated from this class, if specified.
+     *
+     * @param bool $skipmsg If true, raiseError will only pass error codes,
+     *                  the error message parameter will be dropped.
+     *
+     * @access public
+     * @return object   a PEAR error object
+     * @see PEAR::setErrorHandling
+     * @since PHP 4.0.5
+     */
+    function &raiseError($message = null,
+                         $code = null,
+                         $mode = null,
+                         $options = null,
+                         $userinfo = null,
+                         $error_class = null,
+                         $skipmsg = false)
+    {
+        // The error is yet a PEAR error object
+        if (is_object($message)) {
+            $code        = $message->getCode();
+            $userinfo    = $message->getUserInfo();
+            $error_class = $message->getType();
+            $message->error_message_prefix = '';
+            $message     = $message->getMessage();
+        }
+
+        if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {
+            if ($exp[0] == "*" ||
+                (is_int(reset($exp)) && in_array($code, $exp)) ||
+                (is_string(reset($exp)) && in_array($message, $exp))) {
+                $mode = PEAR_ERROR_RETURN;
+            }
+        }
+        // No mode given, try global ones
+        if ($mode === null) {
+            // Class error handler
+            if (isset($this) && isset($this->_default_error_mode)) {
+                $mode    = $this->_default_error_mode;
+                $options = $this->_default_error_options;
+            // Global error handler
+            } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
+                $mode    = $GLOBALS['_PEAR_default_error_mode'];
+                $options = $GLOBALS['_PEAR_default_error_options'];
+            }
+        }
+
+        if ($error_class !== null) {
+            $ec = $error_class;
+        } elseif (isset($this) && isset($this->_error_class)) {
+            $ec = $this->_error_class;
+        } else {
+            $ec = 'PEAR_Error';
+        }
+        if ($skipmsg) {
+            $a = &new $ec($code, $mode, $options, $userinfo);
+            return $a;
+        } else {
+            $a = &new $ec($message, $code, $mode, $options, $userinfo);
+            return $a;
+        }
+    }
+
+    // }}}
+    // {{{ throwError()
+
+    /**
+     * Simpler form of raiseError with fewer options.  In most cases
+     * message, code and userinfo are enough.
+     *
+     * @param string $message
+     *
+     */
+    function &throwError($message = null,
+                         $code = null,
+                         $userinfo = null)
+    {
+        if (isset($this) && is_a($this, 'PEAR')) {
+            $a = &$this->raiseError($message, $code, null, null, $userinfo);
+            return $a;
+        } else {
+            $a = &PEAR::raiseError($message, $code, null, null, $userinfo);
+            return $a;
+        }
+    }
+
+    // }}}
+    function staticPushErrorHandling($mode, $options = null)
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
+        $def_options = &$GLOBALS['_PEAR_default_error_options'];
+        $stack[] = array($def_mode, $def_options);
+        switch ($mode) {
+            case PEAR_ERROR_EXCEPTION:
+            case PEAR_ERROR_RETURN:
+            case PEAR_ERROR_PRINT:
+            case PEAR_ERROR_TRIGGER:
+            case PEAR_ERROR_DIE:
+            case null:
+                $def_mode = $mode;
+                $def_options = $options;
+                break;
+
+            case PEAR_ERROR_CALLBACK:
+                $def_mode = $mode;
+                // class/object method callback
+                if (is_callable($options)) {
+                    $def_options = $options;
+                } else {
+                    trigger_error("invalid error callback", E_USER_WARNING);
+                }
+                break;
+
+            default:
+                trigger_error("invalid error mode", E_USER_WARNING);
+                break;
+        }
+        $stack[] = array($mode, $options);
+        return true;
+    }
+
+    function staticPopErrorHandling()
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
+        $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
+        array_pop($stack);
+        list($mode, $options) = $stack[sizeof($stack) - 1];
+        array_pop($stack);
+        switch ($mode) {
+            case PEAR_ERROR_EXCEPTION:
+            case PEAR_ERROR_RETURN:
+            case PEAR_ERROR_PRINT:
+            case PEAR_ERROR_TRIGGER:
+            case PEAR_ERROR_DIE:
+            case null:
+                $setmode = $mode;
+                $setoptions = $options;
+                break;
+
+            case PEAR_ERROR_CALLBACK:
+                $setmode = $mode;
+                // class/object method callback
+                if (is_callable($options)) {
+                    $setoptions = $options;
+                } else {
+                    trigger_error("invalid error callback", E_USER_WARNING);
+                }
+                break;
+
+            default:
+                trigger_error("invalid error mode", E_USER_WARNING);
+                break;
+        }
+        return true;
+    }
+
+    // {{{ pushErrorHandling()
+
+    /**
+     * Push a new error handler on top of the error handler options stack. With this
+     * you can easily override the actual error handler for some code and restore
+     * it later with popErrorHandling.
+     *
+     * @param mixed $mode (same as setErrorHandling)
+     * @param mixed $options (same as setErrorHandling)
+     *
+     * @return bool Always true
+     *
+     * @see PEAR::setErrorHandling
+     */
+    function pushErrorHandling($mode, $options = null)
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        if (isset($this) && is_a($this, 'PEAR')) {
+            $def_mode    = &$this->_default_error_mode;
+            $def_options = &$this->_default_error_options;
+        } else {
+            $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
+            $def_options = &$GLOBALS['_PEAR_default_error_options'];
+        }
+        $stack[] = array($def_mode, $def_options);
+
+        if (isset($this) && is_a($this, 'PEAR')) {
+            $this->setErrorHandling($mode, $options);
+        } else {
+            PEAR::setErrorHandling($mode, $options);
+        }
+        $stack[] = array($mode, $options);
+        return true;
+    }
+
+    // }}}
+    // {{{ popErrorHandling()
+
+    /**
+    * Pop the last error handler used
+    *
+    * @return bool Always true
+    *
+    * @see PEAR::pushErrorHandling
+    */
+    function popErrorHandling()
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        array_pop($stack);
+        list($mode, $options) = $stack[sizeof($stack) - 1];
+        array_pop($stack);
+        if (isset($this) && is_a($this, 'PEAR')) {
+            $this->setErrorHandling($mode, $options);
+        } else {
+            PEAR::setErrorHandling($mode, $options);
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ loadExtension()
+
+    /**
+    * OS independant PHP extension load. Remember to take care
+    * on the correct extension name for case sensitive OSes.
+    *
+    * @param string $ext The extension name
+    * @return bool Success or not on the dl() call
+    */
+    function loadExtension($ext)
+    {
+        if (!extension_loaded($ext)) {
+            // if either returns true dl() will produce a FATAL error, stop that
+            if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) {
+                return false;
+            }
+            if (OS_WINDOWS) {
+                $suffix = '.dll';
+            } elseif (PHP_OS == 'HP-UX') {
+                $suffix = '.sl';
+            } elseif (PHP_OS == 'AIX') {
+                $suffix = '.a';
+            } elseif (PHP_OS == 'OSX') {
+                $suffix = '.bundle';
+            } else {
+                $suffix = '.so';
+            }
+            return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
+        }
+        return true;
+    }
+
+    // }}}
+}
+
+// {{{ _PEAR_call_destructors()
+
+function _PEAR_call_destructors()
+{
+    global $_PEAR_destructor_object_list;
+    if (is_array($_PEAR_destructor_object_list) &&
+        sizeof($_PEAR_destructor_object_list))
+    {
+        reset($_PEAR_destructor_object_list);
+        if (PEAR::getStaticProperty('PEAR', 'destructlifo')) {
+            $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
+        }
+        while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
+            $classname = get_class($objref);
+            while ($classname) {
+                $destructor = "_$classname";
+                if (method_exists($objref, $destructor)) {
+                    $objref->$destructor();
+                    break;
+                } else {
+                    $classname = get_parent_class($classname);
+                }
+            }
+        }
+        // Empty the object list to ensure that destructors are
+        // not called more than once.
+        $_PEAR_destructor_object_list = array();
+    }
+
+    // Now call the shutdown functions
+    if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
+        foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
+            call_user_func_array($value[0], $value[1]);
+        }
+    }
+}
+
+// }}}
+/**
+ * Standard PEAR error class for PHP 4
+ *
+ * This class is supserseded by {@link PEAR_Exception} in PHP 5
+ *
+ * @category   pear
+ * @package    PEAR
+ * @author     Stig Bakken <ssb@php.net>
+ * @author     Tomas V.V. Cox <cox@idecnet.com>
+ * @author     Gregory Beaver <cellog@php.net>
+ * @copyright  1997-2006 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    Release: 1.6.1
+ * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
+ * @see        PEAR::raiseError(), PEAR::throwError()
+ * @since      Class available since PHP 4.0.2
+ */
+class PEAR_Error
+{
+    // {{{ properties
+
+    var $error_message_prefix = '';
+    var $mode                 = PEAR_ERROR_RETURN;
+    var $level                = E_USER_NOTICE;
+    var $code                 = -1;
+    var $message              = '';
+    var $userinfo             = '';
+    var $backtrace            = null;
+
+    // }}}
+    // {{{ constructor
+
+    /**
+     * PEAR_Error constructor
+     *
+     * @param string $message  message
+     *
+     * @param int $code     (optional) error code
+     *
+     * @param int $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
+     * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
+     * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
+     *
+     * @param mixed $options   (optional) error level, _OR_ in the case of
+     * PEAR_ERROR_CALLBACK, the callback function or object/method
+     * tuple.
+     *
+     * @param string $userinfo (optional) additional user/debug info
+     *
+     * @access public
+     *
+     */
+    function PEAR_Error($message = 'unknown error', $code = null,
+                        $mode = null, $options = null, $userinfo = null)
+    {
+        if ($mode === null) {
+            $mode = PEAR_ERROR_RETURN;
+        }
+        $this->message   = $message;
+        $this->code      = $code;
+        $this->mode      = $mode;
+        $this->userinfo  = $userinfo;
+        if (!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) {
+            $this->backtrace = debug_backtrace();
+            if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
+                unset($this->backtrace[0]['object']);
+            }
+        }
+        if ($mode & PEAR_ERROR_CALLBACK) {
+            $this->level = E_USER_NOTICE;
+            $this->callback = $options;
+        } else {
+            if ($options === null) {
+                $options = E_USER_NOTICE;
+            }
+            $this->level = $options;
+            $this->callback = null;
+        }
+        if ($this->mode & PEAR_ERROR_PRINT) {
+            if (is_null($options) || is_int($options)) {
+                $format = "%s";
+            } else {
+                $format = $options;
+            }
+            printf($format, $this->getMessage());
+        }
+        if ($this->mode & PEAR_ERROR_TRIGGER) {
+            trigger_error($this->getMessage(), $this->level);
+        }
+        if ($this->mode & PEAR_ERROR_DIE) {
+            $msg = $this->getMessage();
+            if (is_null($options) || is_int($options)) {
+                $format = "%s";
+                if (substr($msg, -1) != "\n") {
+                    $msg .= "\n";
+                }
+            } else {
+                $format = $options;
+            }
+            die(sprintf($format, $msg));
+        }
+        if ($this->mode & PEAR_ERROR_CALLBACK) {
+            if (is_callable($this->callback)) {
+                call_user_func($this->callback, $this);
+            }
+        }
+        if ($this->mode & PEAR_ERROR_EXCEPTION) {
+            trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
+            eval('$e = new Exception($this->message, $this->code);throw($e);');
+        }
+    }
+
+    // }}}
+    // {{{ getMode()
+
+    /**
+     * Get the error mode from an error object.
+     *
+     * @return int error mode
+     * @access public
+     */
+    function getMode() {
+        return $this->mode;
+    }
+
+    // }}}
+    // {{{ getCallback()
+
+    /**
+     * Get the callback function/method from an error object.
+     *
+     * @return mixed callback function or object/method array
+     * @access public
+     */
+    function getCallback() {
+        return $this->callback;
+    }
+
+    // }}}
+    // {{{ getMessage()
+
+
+    /**
+     * Get the error message from an error object.
+     *
+     * @return  string  full error message
+     * @access public
+     */
+    function getMessage()
+    {
+        return ($this->error_message_prefix . $this->message);
+    }
+
+
+    // }}}
+    // {{{ getCode()
+
+    /**
+     * Get error code from an error object
+     *
+     * @return int error code
+     * @access public
+     */
+     function getCode()
+     {
+        return $this->code;
+     }
+
+    // }}}
+    // {{{ getType()
+
+    /**
+     * Get the name of this error/exception.
+     *
+     * @return string error/exception name (type)
+     * @access public
+     */
+    function getType()
+    {
+        return get_class($this);
+    }
+
+    // }}}
+    // {{{ getUserInfo()
+
+    /**
+     * Get additional user-supplied information.
+     *
+     * @return string user-supplied information
+     * @access public
+     */
+    function getUserInfo()
+    {
+        return $this->userinfo;
+    }
+
+    // }}}
+    // {{{ getDebugInfo()
+
+    /**
+     * Get additional debug information supplied by the application.
+     *
+     * @return string debug information
+     * @access public
+     */
+    function getDebugInfo()
+    {
+        return $this->getUserInfo();
+    }
+
+    // }}}
+    // {{{ getBacktrace()
+
+    /**
+     * Get the call backtrace from where the error was generated.
+     * Supported with PHP 4.3.0 or newer.
+     *
+     * @param int $frame (optional) what frame to fetch
+     * @return array Backtrace, or NULL if not available.
+     * @access public
+     */
+    function getBacktrace($frame = null)
+    {
+        if (defined('PEAR_IGNORE_BACKTRACE')) {
+            return null;
+        }
+        if ($frame === null) {
+            return $this->backtrace;
+        }
+        return $this->backtrace[$frame];
+    }
+
+    // }}}
+    // {{{ addUserInfo()
+
+    function addUserInfo($info)
+    {
+        if (empty($this->userinfo)) {
+            $this->userinfo = $info;
+        } else {
+            $this->userinfo .= " ** $info";
+        }
+    }
+
+    // }}}
+    // {{{ toString()
+
+    /**
+     * Make a string representation of this object.
+     *
+     * @return string a string with an object summary
+     * @access public
+     */
+    function toString() {
+        $modes = array();
+        $levels = array(E_USER_NOTICE  => 'notice',
+                        E_USER_WARNING => 'warning',
+                        E_USER_ERROR   => 'error');
+        if ($this->mode & PEAR_ERROR_CALLBACK) {
+            if (is_array($this->callback)) {
+                $callback = (is_object($this->callback[0]) ?
+                    strtolower(get_class($this->callback[0])) :
+                    $this->callback[0]) . '::' .
+                    $this->callback[1];
+            } else {
+                $callback = $this->callback;
+            }
+            return sprintf('[%s: message="%s" code=%d mode=callback '.
+                           'callback=%s prefix="%s" info="%s"]',
+                           strtolower(get_class($this)), $this->message, $this->code,
+                           $callback, $this->error_message_prefix,
+                           $this->userinfo);
+        }
+        if ($this->mode & PEAR_ERROR_PRINT) {
+            $modes[] = 'print';
+        }
+        if ($this->mode & PEAR_ERROR_TRIGGER) {
+            $modes[] = 'trigger';
+        }
+        if ($this->mode & PEAR_ERROR_DIE) {
+            $modes[] = 'die';
+        }
+        if ($this->mode & PEAR_ERROR_RETURN) {
+            $modes[] = 'return';
+        }
+        return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
+                       'prefix="%s" info="%s"]',
+                       strtolower(get_class($this)), $this->message, $this->code,
+                       implode("|", $modes), $levels[$this->level],
+                       $this->error_message_prefix,
+                       $this->userinfo);
+    }
+
+    // }}}
+}
+
+/*
+ * Local Variables:
+ * mode: php
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/System.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/pear/System.php
new file mode 100644 (file)
index 0000000..fc879a0
--- /dev/null
@@ -0,0 +1,1108 @@
+<?php
+/**
+ * PEAR, the PHP Extension and Application Repository
+ *
+ * PEAR class and PEAR_Error class
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category   pear
+ * @package    PEAR
+ * @author     Sterling Hughes <sterling@php.net>
+ * @author     Stig Bakken <ssb@php.net>
+ * @author     Tomas V.V.Cox <cox@idecnet.com>
+ * @author     Greg Beaver <cellog@php.net>
+ * @copyright  1997-2006 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    CVS: $Id: PEAR.php,v 1.101 2006/04/25 02:41:03 cellog Exp $
+ * @link       http://pear.php.net/package/PEAR
+ * @since      File available since Release 0.1
+ */
+
+/**#@+
+ * ERROR constants
+ */
+define('PEAR_ERROR_RETURN',     1);
+define('PEAR_ERROR_PRINT',      2);
+define('PEAR_ERROR_TRIGGER',    4);
+define('PEAR_ERROR_DIE',        8);
+define('PEAR_ERROR_CALLBACK',  16);
+/**
+ * WARNING: obsolete
+ * @deprecated
+ */
+define('PEAR_ERROR_EXCEPTION', 32);
+/**#@-*/
+define('PEAR_ZE2', (function_exists('version_compare') &&
+                    version_compare(zend_version(), "2-dev", "ge")));
+
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+    define('OS_WINDOWS', true);
+    define('OS_UNIX',    false);
+    define('PEAR_OS',    'Windows');
+} else {
+    define('OS_WINDOWS', false);
+    define('OS_UNIX',    true);
+    define('PEAR_OS',    'Unix'); // blatant assumption
+}
+
+// instant backwards compatibility
+if (!defined('PATH_SEPARATOR')) {
+    if (OS_WINDOWS) {
+        define('PATH_SEPARATOR', ';');
+    } else {
+        define('PATH_SEPARATOR', ':');
+    }
+}
+
+$GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
+$GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
+$GLOBALS['_PEAR_destructor_object_list'] = array();
+$GLOBALS['_PEAR_shutdown_funcs']         = array();
+$GLOBALS['_PEAR_error_handler_stack']    = array();
+
+@ini_set('track_errors', true);
+
+/**
+ * Base class for other PEAR classes.  Provides rudimentary
+ * emulation of destructors.
+ *
+ * If you want a destructor in your class, inherit PEAR and make a
+ * destructor method called _yourclassname (same name as the
+ * constructor, but with a "_" prefix).  Also, in your constructor you
+ * have to call the PEAR constructor: $this->PEAR();.
+ * The destructor method will be called without parameters.  Note that
+ * at in some SAPI implementations (such as Apache), any output during
+ * the request shutdown (in which destructors are called) seems to be
+ * discarded.  If you need to get any debug information from your
+ * destructor, use error_log(), syslog() or something similar.
+ *
+ * IMPORTANT! To use the emulated destructors you need to create the
+ * objects by reference: $obj =& new PEAR_child;
+ *
+ * @category   pear
+ * @package    PEAR
+ * @author     Stig Bakken <ssb@php.net>
+ * @author     Tomas V.V. Cox <cox@idecnet.com>
+ * @author     Greg Beaver <cellog@php.net>
+ * @copyright  1997-2006 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    Release: 1.6.1
+ * @link       http://pear.php.net/package/PEAR
+ * @see        PEAR_Error
+ * @since      Class available since PHP 4.0.2
+ * @link        http://pear.php.net/manual/en/core.pear.php#core.pear.pear
+ */
+class PEAR
+{
+    // {{{ properties
+
+    /**
+     * Whether to enable internal debug messages.
+     *
+     * @var     bool
+     * @access  private
+     */
+    var $_debug = false;
+
+    /**
+     * Default error mode for this object.
+     *
+     * @var     int
+     * @access  private
+     */
+    var $_default_error_mode = null;
+
+    /**
+     * Default error options used for this object when error mode
+     * is PEAR_ERROR_TRIGGER.
+     *
+     * @var     int
+     * @access  private
+     */
+    var $_default_error_options = null;
+
+    /**
+     * Default error handler (callback) for this object, if error mode is
+     * PEAR_ERROR_CALLBACK.
+     *
+     * @var     string
+     * @access  private
+     */
+    var $_default_error_handler = '';
+
+    /**
+     * Which class to use for error objects.
+     *
+     * @var     string
+     * @access  private
+     */
+    var $_error_class = 'PEAR_Error';
+
+    /**
+     * An array of expected errors.
+     *
+     * @var     array
+     * @access  private
+     */
+    var $_expected_errors = array();
+
+    // }}}
+
+    // {{{ constructor
+
+    /**
+     * Constructor.  Registers this object in
+     * $_PEAR_destructor_object_list for destructor emulation if a
+     * destructor object exists.
+     *
+     * @param string $error_class  (optional) which class to use for
+     *        error objects, defaults to PEAR_Error.
+     * @access public
+     * @return void
+     */
+    function PEAR($error_class = null)
+    {
+        $classname = strtolower(get_class($this));
+        if ($this->_debug) {
+            print "PEAR constructor called, class=$classname\n";
+        }
+        if ($error_class !== null) {
+            $this->_error_class = $error_class;
+        }
+        while ($classname && strcasecmp($classname, "pear")) {
+            $destructor = "_$classname";
+            if (method_exists($this, $destructor)) {
+                global $_PEAR_destructor_object_list;
+                $_PEAR_destructor_object_list[] = &$this;
+                if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
+                    register_shutdown_function("_PEAR_call_destructors");
+                    $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
+                }
+                break;
+            } else {
+                $classname = get_parent_class($classname);
+            }
+        }
+    }
+
+    // }}}
+    // {{{ destructor
+
+    /**
+     * Destructor (the emulated type of...).  Does nothing right now,
+     * but is included for forward compatibility, so subclass
+     * destructors should always call it.
+     *
+     * See the note in the class desciption about output from
+     * destructors.
+     *
+     * @access public
+     * @return void
+     */
+    function _PEAR() {
+        if ($this->_debug) {
+            printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
+        }
+    }
+
+    // }}}
+    // {{{ getStaticProperty()
+
+    /**
+    * If you have a class that's mostly/entirely static, and you need static
+    * properties, you can use this method to simulate them. Eg. in your method(s)
+    * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
+    * You MUST use a reference, or they will not persist!
+    *
+    * @access public
+    * @param  string $class  The calling classname, to prevent clashes
+    * @param  string $var    The variable to retrieve.
+    * @return mixed   A reference to the variable. If not set it will be
+    *                 auto initialised to NULL.
+    */
+    function &getStaticProperty($class, $var)
+    {
+        static $properties;
+        if (!isset($properties[$class])) {
+            $properties[$class] = array();
+        }
+        if (!array_key_exists($var, $properties[$class])) {
+            $properties[$class][$var] = null;
+        }
+        return $properties[$class][$var];
+    }
+
+    // }}}
+    // {{{ registerShutdownFunc()
+
+    /**
+    * Use this function to register a shutdown method for static
+    * classes.
+    *
+    * @access public
+    * @param  mixed $func  The function name (or array of class/method) to call
+    * @param  mixed $args  The arguments to pass to the function
+    * @return void
+    */
+    function registerShutdownFunc($func, $args = array())
+    {
+        // if we are called statically, there is a potential
+        // that no shutdown func is registered.  Bug #6445
+        if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
+            register_shutdown_function("_PEAR_call_destructors");
+            $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
+        }
+        $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
+    }
+
+    // }}}
+    // {{{ isError()
+
+    /**
+     * Tell whether a value is a PEAR error.
+     *
+     * @param   mixed $data   the value to test
+     * @param   int   $code   if $data is an error object, return true
+     *                        only if $code is a string and
+     *                        $obj->getMessage() == $code or
+     *                        $code is an integer and $obj->getCode() == $code
+     * @access  public
+     * @return  bool    true if parameter is an error
+     */
+    function isError($data, $code = null)
+    {
+        if (is_a($data, 'PEAR_Error')) {
+            if (is_null($code)) {
+                return true;
+            } elseif (is_string($code)) {
+                return $data->getMessage() == $code;
+            } else {
+                return $data->getCode() == $code;
+            }
+        }
+        return false;
+    }
+
+    // }}}
+    // {{{ setErrorHandling()
+
+    /**
+     * Sets how errors generated by this object should be handled.
+     * Can be invoked both in objects and statically.  If called
+     * statically, setErrorHandling sets the default behaviour for all
+     * PEAR objects.  If called in an object, setErrorHandling sets
+     * the default behaviour for that object.
+     *
+     * @param int $mode
+     *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
+     *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
+     *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
+     *
+     * @param mixed $options
+     *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
+     *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
+     *
+     *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
+     *        to be the callback function or method.  A callback
+     *        function is a string with the name of the function, a
+     *        callback method is an array of two elements: the element
+     *        at index 0 is the object, and the element at index 1 is
+     *        the name of the method to call in the object.
+     *
+     *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
+     *        a printf format string used when printing the error
+     *        message.
+     *
+     * @access public
+     * @return void
+     * @see PEAR_ERROR_RETURN
+     * @see PEAR_ERROR_PRINT
+     * @see PEAR_ERROR_TRIGGER
+     * @see PEAR_ERROR_DIE
+     * @see PEAR_ERROR_CALLBACK
+     * @see PEAR_ERROR_EXCEPTION
+     *
+     * @since PHP 4.0.5
+     */
+
+    function setErrorHandling($mode = null, $options = null)
+    {
+        if (isset($this) && is_a($this, 'PEAR')) {
+            $setmode     = &$this->_default_error_mode;
+            $setoptions  = &$this->_default_error_options;
+        } else {
+            $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
+            $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
+        }
+
+        switch ($mode) {
+            case PEAR_ERROR_EXCEPTION:
+            case PEAR_ERROR_RETURN:
+            case PEAR_ERROR_PRINT:
+            case PEAR_ERROR_TRIGGER:
+            case PEAR_ERROR_DIE:
+            case null:
+                $setmode = $mode;
+                $setoptions = $options;
+                break;
+
+            case PEAR_ERROR_CALLBACK:
+                $setmode = $mode;
+                // class/object method callback
+                if (is_callable($options)) {
+                    $setoptions = $options;
+                } else {
+                    trigger_error("invalid error callback", E_USER_WARNING);
+                }
+                break;
+
+            default:
+                trigger_error("invalid error mode", E_USER_WARNING);
+                break;
+        }
+    }
+
+    // }}}
+    // {{{ expectError()
+
+    /**
+     * This method is used to tell which errors you expect to get.
+     * Expected errors are always returned with error mode
+     * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
+     * and this method pushes a new element onto it.  The list of
+     * expected errors are in effect until they are popped off the
+     * stack with the popExpect() method.
+     *
+     * Note that this method can not be called statically
+     *
+     * @param mixed $code a single error code or an array of error codes to expect
+     *
+     * @return int     the new depth of the "expected errors" stack
+     * @access public
+     */
+    function expectError($code = '*')
+    {
+        if (is_array($code)) {
+            array_push($this->_expected_errors, $code);
+        } else {
+            array_push($this->_expected_errors, array($code));
+        }
+        return sizeof($this->_expected_errors);
+    }
+
+    // }}}
+    // {{{ popExpect()
+
+    /**
+     * This method pops one element off the expected error codes
+     * stack.
+     *
+     * @return array   the list of error codes that were popped
+     */
+    function popExpect()
+    {
+        return array_pop($this->_expected_errors);
+    }
+
+    // }}}
+    // {{{ _checkDelExpect()
+
+    /**
+     * This method checks unsets an error code if available
+     *
+     * @param mixed error code
+     * @return bool true if the error code was unset, false otherwise
+     * @access private
+     * @since PHP 4.3.0
+     */
+    function _checkDelExpect($error_code)
+    {
+        $deleted = false;
+
+        foreach ($this->_expected_errors AS $key => $error_array) {
+            if (in_array($error_code, $error_array)) {
+                unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
+                $deleted = true;
+            }
+
+            // clean up empty arrays
+            if (0 == count($this->_expected_errors[$key])) {
+                unset($this->_expected_errors[$key]);
+            }
+        }
+        return $deleted;
+    }
+
+    // }}}
+    // {{{ delExpect()
+
+    /**
+     * This method deletes all occurences of the specified element from
+     * the expected error codes stack.
+     *
+     * @param  mixed $error_code error code that should be deleted
+     * @return mixed list of error codes that were deleted or error
+     * @access public
+     * @since PHP 4.3.0
+     */
+    function delExpect($error_code)
+    {
+        $deleted = false;
+
+        if ((is_array($error_code) && (0 != count($error_code)))) {
+            // $error_code is a non-empty array here;
+            // we walk through it trying to unset all
+            // values
+            foreach($error_code as $key => $error) {
+                if ($this->_checkDelExpect($error)) {
+                    $deleted =  true;
+                } else {
+                    $deleted = false;
+                }
+            }
+            return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
+        } elseif (!empty($error_code)) {
+            // $error_code comes alone, trying to unset it
+            if ($this->_checkDelExpect($error_code)) {
+                return true;
+            } else {
+                return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
+            }
+        } else {
+            // $error_code is empty
+            return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
+        }
+    }
+
+    // }}}
+    // {{{ raiseError()
+
+    /**
+     * This method is a wrapper that returns an instance of the
+     * configured error class with this object's default error
+     * handling applied.  If the $mode and $options parameters are not
+     * specified, the object's defaults are used.
+     *
+     * @param mixed $message a text error message or a PEAR error object
+     *
+     * @param int $code      a numeric error code (it is up to your class
+     *                  to define these if you want to use codes)
+     *
+     * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
+     *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
+     *                  PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
+     *
+     * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
+     *                  specifies the PHP-internal error level (one of
+     *                  E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
+     *                  If $mode is PEAR_ERROR_CALLBACK, this
+     *                  parameter specifies the callback function or
+     *                  method.  In other error modes this parameter
+     *                  is ignored.
+     *
+     * @param string $userinfo If you need to pass along for example debug
+     *                  information, this parameter is meant for that.
+     *
+     * @param string $error_class The returned error object will be
+     *                  instantiated from this class, if specified.
+     *
+     * @param bool $skipmsg If true, raiseError will only pass error codes,
+     *                  the error message parameter will be dropped.
+     *
+     * @access public
+     * @return object   a PEAR error object
+     * @see PEAR::setErrorHandling
+     * @since PHP 4.0.5
+     */
+    function &raiseError($message = null,
+                         $code = null,
+                         $mode = null,
+                         $options = null,
+                         $userinfo = null,
+                         $error_class = null,
+                         $skipmsg = false)
+    {
+        // The error is yet a PEAR error object
+        if (is_object($message)) {
+            $code        = $message->getCode();
+            $userinfo    = $message->getUserInfo();
+            $error_class = $message->getType();
+            $message->error_message_prefix = '';
+            $message     = $message->getMessage();
+        }
+
+        if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {
+            if ($exp[0] == "*" ||
+                (is_int(reset($exp)) && in_array($code, $exp)) ||
+                (is_string(reset($exp)) && in_array($message, $exp))) {
+                $mode = PEAR_ERROR_RETURN;
+            }
+        }
+        // No mode given, try global ones
+        if ($mode === null) {
+            // Class error handler
+            if (isset($this) && isset($this->_default_error_mode)) {
+                $mode    = $this->_default_error_mode;
+                $options = $this->_default_error_options;
+            // Global error handler
+            } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
+                $mode    = $GLOBALS['_PEAR_default_error_mode'];
+                $options = $GLOBALS['_PEAR_default_error_options'];
+            }
+        }
+
+        if ($error_class !== null) {
+            $ec = $error_class;
+        } elseif (isset($this) && isset($this->_error_class)) {
+            $ec = $this->_error_class;
+        } else {
+            $ec = 'PEAR_Error';
+        }
+        if ($skipmsg) {
+            $a = &new $ec($code, $mode, $options, $userinfo);
+            return $a;
+        } else {
+            $a = &new $ec($message, $code, $mode, $options, $userinfo);
+            return $a;
+        }
+    }
+
+    // }}}
+    // {{{ throwError()
+
+    /**
+     * Simpler form of raiseError with fewer options.  In most cases
+     * message, code and userinfo are enough.
+     *
+     * @param string $message
+     *
+     */
+    function &throwError($message = null,
+                         $code = null,
+                         $userinfo = null)
+    {
+        if (isset($this) && is_a($this, 'PEAR')) {
+            $a = &$this->raiseError($message, $code, null, null, $userinfo);
+            return $a;
+        } else {
+            $a = &PEAR::raiseError($message, $code, null, null, $userinfo);
+            return $a;
+        }
+    }
+
+    // }}}
+    function staticPushErrorHandling($mode, $options = null)
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
+        $def_options = &$GLOBALS['_PEAR_default_error_options'];
+        $stack[] = array($def_mode, $def_options);
+        switch ($mode) {
+            case PEAR_ERROR_EXCEPTION:
+            case PEAR_ERROR_RETURN:
+            case PEAR_ERROR_PRINT:
+            case PEAR_ERROR_TRIGGER:
+            case PEAR_ERROR_DIE:
+            case null:
+                $def_mode = $mode;
+                $def_options = $options;
+                break;
+
+            case PEAR_ERROR_CALLBACK:
+                $def_mode = $mode;
+                // class/object method callback
+                if (is_callable($options)) {
+                    $def_options = $options;
+                } else {
+                    trigger_error("invalid error callback", E_USER_WARNING);
+                }
+                break;
+
+            default:
+                trigger_error("invalid error mode", E_USER_WARNING);
+                break;
+        }
+        $stack[] = array($mode, $options);
+        return true;
+    }
+
+    function staticPopErrorHandling()
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
+        $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
+        array_pop($stack);
+        list($mode, $options) = $stack[sizeof($stack) - 1];
+        array_pop($stack);
+        switch ($mode) {
+            case PEAR_ERROR_EXCEPTION:
+            case PEAR_ERROR_RETURN:
+            case PEAR_ERROR_PRINT:
+            case PEAR_ERROR_TRIGGER:
+            case PEAR_ERROR_DIE:
+            case null:
+                $setmode = $mode;
+                $setoptions = $options;
+                break;
+
+            case PEAR_ERROR_CALLBACK:
+                $setmode = $mode;
+                // class/object method callback
+                if (is_callable($options)) {
+                    $setoptions = $options;
+                } else {
+                    trigger_error("invalid error callback", E_USER_WARNING);
+                }
+                break;
+
+            default:
+                trigger_error("invalid error mode", E_USER_WARNING);
+                break;
+        }
+        return true;
+    }
+
+    // {{{ pushErrorHandling()
+
+    /**
+     * Push a new error handler on top of the error handler options stack. With this
+     * you can easily override the actual error handler for some code and restore
+     * it later with popErrorHandling.
+     *
+     * @param mixed $mode (same as setErrorHandling)
+     * @param mixed $options (same as setErrorHandling)
+     *
+     * @return bool Always true
+     *
+     * @see PEAR::setErrorHandling
+     */
+    function pushErrorHandling($mode, $options = null)
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        if (isset($this) && is_a($this, 'PEAR')) {
+            $def_mode    = &$this->_default_error_mode;
+            $def_options = &$this->_default_error_options;
+        } else {
+            $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
+            $def_options = &$GLOBALS['_PEAR_default_error_options'];
+        }
+        $stack[] = array($def_mode, $def_options);
+
+        if (isset($this) && is_a($this, 'PEAR')) {
+            $this->setErrorHandling($mode, $options);
+        } else {
+            PEAR::setErrorHandling($mode, $options);
+        }
+        $stack[] = array($mode, $options);
+        return true;
+    }
+
+    // }}}
+    // {{{ popErrorHandling()
+
+    /**
+    * Pop the last error handler used
+    *
+    * @return bool Always true
+    *
+    * @see PEAR::pushErrorHandling
+    */
+    function popErrorHandling()
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        array_pop($stack);
+        list($mode, $options) = $stack[sizeof($stack) - 1];
+        array_pop($stack);
+        if (isset($this) && is_a($this, 'PEAR')) {
+            $this->setErrorHandling($mode, $options);
+        } else {
+            PEAR::setErrorHandling($mode, $options);
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ loadExtension()
+
+    /**
+    * OS independant PHP extension load. Remember to take care
+    * on the correct extension name for case sensitive OSes.
+    *
+    * @param string $ext The extension name
+    * @return bool Success or not on the dl() call
+    */
+    function loadExtension($ext)
+    {
+        if (!extension_loaded($ext)) {
+            // if either returns true dl() will produce a FATAL error, stop that
+            if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) {
+                return false;
+            }
+            if (OS_WINDOWS) {
+                $suffix = '.dll';
+            } elseif (PHP_OS == 'HP-UX') {
+                $suffix = '.sl';
+            } elseif (PHP_OS == 'AIX') {
+                $suffix = '.a';
+            } elseif (PHP_OS == 'OSX') {
+                $suffix = '.bundle';
+            } else {
+                $suffix = '.so';
+            }
+            return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
+        }
+        return true;
+    }
+
+    // }}}
+}
+
+// {{{ _PEAR_call_destructors()
+
+function _PEAR_call_destructors()
+{
+    global $_PEAR_destructor_object_list;
+    if (is_array($_PEAR_destructor_object_list) &&
+        sizeof($_PEAR_destructor_object_list))
+    {
+        reset($_PEAR_destructor_object_list);
+        if (PEAR::getStaticProperty('PEAR', 'destructlifo')) {
+            $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
+        }
+        while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
+            $classname = get_class($objref);
+            while ($classname) {
+                $destructor = "_$classname";
+                if (method_exists($objref, $destructor)) {
+                    $objref->$destructor();
+                    break;
+                } else {
+                    $classname = get_parent_class($classname);
+                }
+            }
+        }
+        // Empty the object list to ensure that destructors are
+        // not called more than once.
+        $_PEAR_destructor_object_list = array();
+    }
+
+    // Now call the shutdown functions
+    if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
+        foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
+            call_user_func_array($value[0], $value[1]);
+        }
+    }
+}
+
+// }}}
+/**
+ * Standard PEAR error class for PHP 4
+ *
+ * This class is supserseded by {@link PEAR_Exception} in PHP 5
+ *
+ * @category   pear
+ * @package    PEAR
+ * @author     Stig Bakken <ssb@php.net>
+ * @author     Tomas V.V. Cox <cox@idecnet.com>
+ * @author     Gregory Beaver <cellog@php.net>
+ * @copyright  1997-2006 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    Release: 1.6.1
+ * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
+ * @see        PEAR::raiseError(), PEAR::throwError()
+ * @since      Class available since PHP 4.0.2
+ */
+class PEAR_Error
+{
+    // {{{ properties
+
+    var $error_message_prefix = '';
+    var $mode                 = PEAR_ERROR_RETURN;
+    var $level                = E_USER_NOTICE;
+    var $code                 = -1;
+    var $message              = '';
+    var $userinfo             = '';
+    var $backtrace            = null;
+
+    // }}}
+    // {{{ constructor
+
+    /**
+     * PEAR_Error constructor
+     *
+     * @param string $message  message
+     *
+     * @param int $code     (optional) error code
+     *
+     * @param int $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
+     * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
+     * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
+     *
+     * @param mixed $options   (optional) error level, _OR_ in the case of
+     * PEAR_ERROR_CALLBACK, the callback function or object/method
+     * tuple.
+     *
+     * @param string $userinfo (optional) additional user/debug info
+     *
+     * @access public
+     *
+     */
+    function PEAR_Error($message = 'unknown error', $code = null,
+                        $mode = null, $options = null, $userinfo = null)
+    {
+        if ($mode === null) {
+            $mode = PEAR_ERROR_RETURN;
+        }
+        $this->message   = $message;
+        $this->code      = $code;
+        $this->mode      = $mode;
+        $this->userinfo  = $userinfo;
+        if (!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) {
+            $this->backtrace = debug_backtrace();
+            if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
+                unset($this->backtrace[0]['object']);
+            }
+        }
+        if ($mode & PEAR_ERROR_CALLBACK) {
+            $this->level = E_USER_NOTICE;
+            $this->callback = $options;
+        } else {
+            if ($options === null) {
+                $options = E_USER_NOTICE;
+            }
+            $this->level = $options;
+            $this->callback = null;
+        }
+        if ($this->mode & PEAR_ERROR_PRINT) {
+            if (is_null($options) || is_int($options)) {
+                $format = "%s";
+            } else {
+                $format = $options;
+            }
+            printf($format, $this->getMessage());
+        }
+        if ($this->mode & PEAR_ERROR_TRIGGER) {
+            trigger_error($this->getMessage(), $this->level);
+        }
+        if ($this->mode & PEAR_ERROR_DIE) {
+            $msg = $this->getMessage();
+            if (is_null($options) || is_int($options)) {
+                $format = "%s";
+                if (substr($msg, -1) != "\n") {
+                    $msg .= "\n";
+                }
+            } else {
+                $format = $options;
+            }
+            die(sprintf($format, $msg));
+        }
+        if ($this->mode & PEAR_ERROR_CALLBACK) {
+            if (is_callable($this->callback)) {
+                call_user_func($this->callback, $this);
+            }
+        }
+        if ($this->mode & PEAR_ERROR_EXCEPTION) {
+            trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
+            eval('$e = new Exception($this->message, $this->code);throw($e);');
+        }
+    }
+
+    // }}}
+    // {{{ getMode()
+
+    /**
+     * Get the error mode from an error object.
+     *
+     * @return int error mode
+     * @access public
+     */
+    function getMode() {
+        return $this->mode;
+    }
+
+    // }}}
+    // {{{ getCallback()
+
+    /**
+     * Get the callback function/method from an error object.
+     *
+     * @return mixed callback function or object/method array
+     * @access public
+     */
+    function getCallback() {
+        return $this->callback;
+    }
+
+    // }}}
+    // {{{ getMessage()
+
+
+    /**
+     * Get the error message from an error object.
+     *
+     * @return  string  full error message
+     * @access public
+     */
+    function getMessage()
+    {
+        return ($this->error_message_prefix . $this->message);
+    }
+
+
+    // }}}
+    // {{{ getCode()
+
+    /**
+     * Get error code from an error object
+     *
+     * @return int error code
+     * @access public
+     */
+     function getCode()
+     {
+        return $this->code;
+     }
+
+    // }}}
+    // {{{ getType()
+
+    /**
+     * Get the name of this error/exception.
+     *
+     * @return string error/exception name (type)
+     * @access public
+     */
+    function getType()
+    {
+        return get_class($this);
+    }
+
+    // }}}
+    // {{{ getUserInfo()
+
+    /**
+     * Get additional user-supplied information.
+     *
+     * @return string user-supplied information
+     * @access public
+     */
+    function getUserInfo()
+    {
+        return $this->userinfo;
+    }
+
+    // }}}
+    // {{{ getDebugInfo()
+
+    /**
+     * Get additional debug information supplied by the application.
+     *
+     * @return string debug information
+     * @access public
+     */
+    function getDebugInfo()
+    {
+        return $this->getUserInfo();
+    }
+
+    // }}}
+    // {{{ getBacktrace()
+
+    /**
+     * Get the call backtrace from where the error was generated.
+     * Supported with PHP 4.3.0 or newer.
+     *
+     * @param int $frame (optional) what frame to fetch
+     * @return array Backtrace, or NULL if not available.
+     * @access public
+     */
+    function getBacktrace($frame = null)
+    {
+        if (defined('PEAR_IGNORE_BACKTRACE')) {
+            return null;
+        }
+        if ($frame === null) {
+            return $this->backtrace;
+        }
+        return $this->backtrace[$frame];
+    }
+
+    // }}}
+    // {{{ addUserInfo()
+
+    function addUserInfo($info)
+    {
+        if (empty($this->userinfo)) {
+            $this->userinfo = $info;
+        } else {
+            $this->userinfo .= " ** $info";
+        }
+    }
+
+    // }}}
+    // {{{ toString()
+
+    /**
+     * Make a string representation of this object.
+     *
+     * @return string a string with an object summary
+     * @access public
+     */
+    function toString() {
+        $modes = array();
+        $levels = array(E_USER_NOTICE  => 'notice',
+                        E_USER_WARNING => 'warning',
+                        E_USER_ERROR   => 'error');
+        if ($this->mode & PEAR_ERROR_CALLBACK) {
+            if (is_array($this->callback)) {
+                $callback = (is_object($this->callback[0]) ?
+                    strtolower(get_class($this->callback[0])) :
+                    $this->callback[0]) . '::' .
+                    $this->callback[1];
+            } else {
+                $callback = $this->callback;
+            }
+            return sprintf('[%s: message="%s" code=%d mode=callback '.
+                           'callback=%s prefix="%s" info="%s"]',
+                           strtolower(get_class($this)), $this->message, $this->code,
+                           $callback, $this->error_message_prefix,
+                           $this->userinfo);
+        }
+        if ($this->mode & PEAR_ERROR_PRINT) {
+            $modes[] = 'print';
+        }
+        if ($this->mode & PEAR_ERROR_TRIGGER) {
+            $modes[] = 'trigger';
+        }
+        if ($this->mode & PEAR_ERROR_DIE) {
+            $modes[] = 'die';
+        }
+        if ($this->mode & PEAR_ERROR_RETURN) {
+            $modes[] = 'return';
+        }
+        return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
+                       'prefix="%s" info="%s"]',
+                       strtolower(get_class($this)), $this->message, $this->code,
+                       implode("|", $modes), $levels[$this->level],
+                       $this->error_message_prefix,
+                       $this->userinfo);
+    }
+
+    // }}}
+}
+
+/*
+ * Local Variables:
+ * mode: php
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/includes/session.class.php b/ipf/admin/media/tiny_mce/plugins/kfm/includes/session.class.php
new file mode 100644 (file)
index 0000000..ab78e3a
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+$sessionInstances=array();
+class kfmSession extends kfmObject{
+       var $vars;
+       var $id;
+       function kfmSession($key=''){
+               global $kfm;
+               parent::__construct();
+               $create=1;
+               if($key=='' && isset($_COOKIE['kfm_cookie']) && strlen($_COOKIE['kfm_cookie'])==32){
+                       $key=$_COOKIE['kfm_cookie'];
+               }
+               if($key!='' && strlen($key)==32){
+                       $res=db_fetch_row("SELECT id FROM ".KFM_DB_PREFIX."session WHERE cookie='".$key."'");
+                       if(is_array($res) && count($res)){
+                               $create=0;
+                               $this->id=$res['id'];
+                               $this->isNew=false;
+                               $kfm->db->query("UPDATE ".KFM_DB_PREFIX."session SET last_accessed='".date('Y-m-d G:i:s')."' WHERE id='".$this->id."'");
+                       }
+               }
+               if($create){
+                       $kfm->db->query("INSERT INTO ".KFM_DB_PREFIX."session (last_accessed) VALUES ('".date('Y-m-d G:i:s')."')");
+                       $this->id=$kfm->db->lastInsertId(KFM_DB_PREFIX.'session','id');
+                       $key=md5($this->id);
+                       $kfm->db->query("UPDATE ".KFM_DB_PREFIX."session SET cookie='".$key."' WHERE id=".$this->id);
+                       $this->isNew=true;
+               }
+               $this->key=$key;
+               $this->vars=array();
+               setcookie('kfm_cookie',$key,0,'/');
+       }
+       function __construct($key=''){
+               $this->kfmSession($key);
+       }
+       function getInstance($id=0){
+               if(!$id)return false;
+               global $sessionInstances;
+               if(!isset($sessionInstances[$id]))$sessionInstances[$id]=new kfmSession($id);
+               return $sessionInstances[$id];
+       }
+       function set($name='',$value=''){
+               global $kfm;
+               if(isset($this->vars[$name])&&$this->vars[$name]==$value)return;
+               $this->vars[$name]=$value;
+               $kfm->db->query("DELETE FROM ".KFM_DB_PREFIX."session_vars WHERE session_id=".$this->id." and varname='".sql_escape($name)."'");
+               $kfm->db->query("INSERT INTO ".KFM_DB_PREFIX."session_vars (session_id,varname,varvalue) VALUES (".$this->id.",'".sql_escape($name)."','".sql_escape(json_encode($value))."')");
+       }
+       function setMultiple($vars){
+               foreach($vars as $key=>$val)$this->set($key,$val);
+       }
+       function get($name){
+               if(isset($this->vars[$name]))return $this->vars[$name];
+               $res=db_fetch_row("SELECT varvalue FROM ".KFM_DB_PREFIX."session_vars WHERE session_id=".$this->id." and varname='".sql_escape($name)."'");
+               if(count($res)){
+                       $ret=json_decode('['.stripslashes($res['varvalue']).']',true);
+                       if(count($ret))$ret=$ret[0];
+                       else $ret='';
+                       $this->vars[$name]=$ret;
+                       return $ret;
+               }
+               return null;
+       }
+}
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/index.php b/ipf/admin/media/tiny_mce/plugins/kfm/index.php
new file mode 100644 (file)
index 0000000..5c5ab9f
--- /dev/null
@@ -0,0 +1,254 @@
+<?php
+/**
+ * KFM - Kae's File Manager - index page
+ *
+ * @category None
+ * @package  None
+ * @author   Kae Verens <kae@verens.com>
+ * @author   Benjamin ter Kuile <bterkuile@gmail.com>
+ * @license  docs/license.txt for licensing
+ * @link     http://kfm.verens.com/
+ */
+// {{{ setup
+error_reporting(E_ALL);
+require_once 'initialise.php';
+require_once KFM_BASE_PATH.'includes/kaejax.php';
+$kfm_session->set('kfm_url',dirname((!empty($_SERVER['HTTPS'])) ? "https://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] : "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']).DIRECTORY_SEPARATOR);
+$kfm_root_dir = kfmDirectory::getInstance(1);
+if ($kfm_user_root_folder) {
+    $dirs   = explode(DIRECTORY_SEPARATOR, trim($kfm_user_root_folder, ' '.DIRECTORY_SEPARATOR));
+    $subdir = $kfm_root_dir;
+    foreach ($dirs as $dirname) {
+        $subdir = $subdir->getSubdir($dirname);
+        if(!$subdir) die ('Error: Root directory cannot be found in the database.');
+        $kfm_root_folder_id = $subdir->id;
+    }
+    $user_root_dir = $subdir;
+} else {
+    $user_root_dir = $kfm_root_dir;
+}
+$kfm_root_folder_id = $user_root_dir->id;
+if($kfm_root_folder_name=='foldername')$kfm_root_folder_name = $user_root_dir->name;
+$kfm_startupfolder_id = $user_root_dir->id;
+$startup_sequence     = '[]';
+if ($kfm_startup_folder) {
+    $dirs                   = explode(DIRECTORY_SEPARATOR, trim($kfm_startup_folder, ' '.DIRECTORY_SEPARATOR));
+    $subdir                 = $user_root_dir;
+    $startup_sequence_array = array();
+    foreach ($dirs as $dirname) {
+        $subdir = $subdir->getSubdir($dirname);
+        if(!$subdir)break;
+        $startup_sequence_array[] = $subdir->id;
+        $kfm_startupfolder_id     = $subdir->id;
+    }
+    $kfm_session->set('cwd_id', $kfm_startupfolder_id);
+    $startup_sequence = '['.implode(',', $startup_sequence_array).']';
+}
+else if (isset($_GET['fid']) && $_GET['fid']) {
+       $f = kfmFile::getInstance($_GET['fid']);
+       if($f){
+               $_GET['cwd']               = $f->parent;
+               $kfm_startup_selectedFiles = array($_GET['fid']);
+       }
+}
+if (isset($_GET['cwd']) && (int)$_GET['cwd']) {
+       $path   = kfm_getDirectoryParentsArr($_GET['cwd']);
+       $path[] = $_GET['cwd'];
+       if(count($path)>1){
+               $startup_sequence_array = $path;
+               $kfm_startupfolder_id   = $_GET['cwd'];
+               $kfm_session->set('cwd_id', $kfm_startupfolder_id);
+               $startup_sequence = '['.implode(',', $startup_sequence_array).']';
+       }
+}
+// }}}
+header('Content-type: text/html; Charset = utf-8');
+// {{{ export kaejax stuff
+/*
+kfm_kaejax_export('kfm_changeCaption', 'kfm_copyFiles', 'kfm_createDirectory',
+    'kfm_createEmptyFile', 'kfm_deleteDirectory', 'kfm_downloadFileFromUrl',
+    'kfm_extractZippedFile', 'kfm_getFileDetails', 'kfm_getFileUrl', 'kfm_getFileUrls',
+    'kfm_getTagName', 'kfm_getTextFile', 'kfm_getThumbnail', 'kfm_loadDirectories',
+    'kfm_loadFiles', 'kfm_moveDirectory', 'kfm_moveFiles', 'kfm_renameDirectory',
+    'kfm_renameFile', 'kfm_renameFiles', 'kfm_resizeImage', 'kfm_resizeImages', 'kfm_rm',
+    'kfm_rotateImage', 'kfm_cropToOriginal', 'kfm_cropToNew', 'kfm_saveTextFile',
+    'kfm_search', 'kfm_tagAdd', 'kfm_tagRemove', 'kfm_zip');
+*/
+kfm_kaejax_export('kfm_changeCaption', 'kfm_copyFiles', 'kfm_createDirectory',
+    'kfm_createEmptyFile', 'kfm_deleteDirectory', 'kfm_downloadFileFromUrl',
+    'kfm_extractZippedFile', 'kfm_getFileDetails', 'kfm_getFileUrl', 'kfm_getFileUrls',
+    'kfm_getTextFile', 'kfm_getThumbnail', 'kfm_loadDirectories',
+    'kfm_loadFiles', 'kfm_moveDirectory', 'kfm_moveFiles', 'kfm_renameDirectory',
+    'kfm_renameFile', 'kfm_renameFiles', 'kfm_resizeImage', 'kfm_resizeImages', 'kfm_rm',
+    'kfm_cropToOriginal', 'kfm_cropToNew', 'kfm_saveTextFile',
+    'kfm_search', 'kfm_zip');
+if(!empty($_POST['kaejax']))kfm_kaejax_handle_client_request();
+// }}}
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+    <head>
+        <style type="text/css">@import "themes/<?php echo $kfm_theme; ?>/css.php";</style>
+        <title>File Manager</title>
+<?php // {{{ get list of plugins and show their CSS files
+$plugins = array();
+$h       = opendir(KFM_BASE_PATH.'plugins');
+while (false!==($plugin=readdir($h))) {
+    if($plugin[0]=='.')continue;
+    $plugins[] = $plugin;
+    if(file_exists(KFM_BASE_PATH.'plugins/'.$plugin.'/plugin.css'))echo '
+    <link rel="stylesheet" href="plugins/'.$plugin.'/plugin.css" />';
+}
+// }}} ?>
+    </head>
+    <body>
+        <div id="removeme">
+            <p>Please Wait - loading...</p>
+            <noscript>KFM relies on JavaScript. Please either turn on JavaScript in your browser, or <a href="http://www.getfirefox.com/">get Firefox</a> if your browser does not support JavaScript.</noscript>
+        </div>
+<?php
+// {{{ if there's a template, show it here
+$templated = 0;
+if (file_exists('themes/'.$kfm_theme.'/template.html')) {
+    echo '<div id="templateWrapper" style="display:none">'.file_get_contents('themes/'.$kfm_theme.'/template.html').'</div>';
+    $templated = 1;
+}
+// }}}
+// {{{ daily tasks
+$today             = date('Y-m-d');
+/*
+$last_registration = isset($kfm_parameters['last_registration'])?$kfm_parameters['last_registration']:'';
+if ($last_registration!=$today) {
+// {{{ database maintenance
+    echo '<iframe style="display:none" src="maintenance.php"></iframe>';
+// }}}
+// {{{ once per day, tell the kfm website a few simple details about usage
+    if (!$kfm_dont_send_metrics) {
+        echo '<img src="http://kfm.verens.com/extras/register.php?version='.urlencode(KFM_VERSION).
+            '&amp;domain_name='.urlencode($_SERVER['SERVER_NAME']).
+            '&amp;db_type='.$kfm_db_type.
+            '&amp;plugins='.join(',',$plugins).
+        '" />';
+    }
+// }}}
+    $kfmdb->query("delete from ".KFM_DB_PREFIX."parameters where name='last_registration'");
+    $kfmdb->query("insert into ".KFM_DB_PREFIX."parameters (name,value) values ('last_registration','".$today."')");
+    $kfm_parameters['last_registration'] = $today;
+}
+// }}}
+*/
+
+// {{{ check for default directories
+if($kfm_default_directories!=''){
+       $dirs=explode(',',$kfm_default_directories);
+       foreach($dirs as $dir){
+               $dir=trim($dir);
+               @mkdir($rootdir.$dir,0755);
+       }
+}
+// }}}
+?>
+        <script type="text/javascript" src="j/mootools.v1.11/mootools.v1.11.js"></script>
+        <script type="text/javascript" src="j/jquery/all.php"></script>
+<?php // {{{ set up JavaScript environment variables ?>
+        <script type="text/javascript">
+            var $j = jQuery.noConflict();
+            $j.tablesorter.addParser({
+                id: 'kfmobject',
+                is: function(s) {
+                    return false;
+                },
+                format: function(s) {
+                    return $j(s).text().toLowerCase();
+                },
+                type: 'text'
+            });
+            var kfm_vars={
+                files:{
+                    name_length_displayed:<?php echo $kfm_files_name_length_displayed; ?>,
+                    name_length_in_list:<?php echo $kfm_files_name_length_in_list; ?>,
+                    return_id_to_cms:<?php echo $kfm_return_file_id_to_cms?'true':'false'; ?>,
+                    allow_multiple_returns:<?php echo $kfm_allow_multiple_file_returns?'true':'false'; ?>,
+                                                                               drags_move_or_copy:<?php echo $kfm_drags_move_or_copy_files; ?>
+                },
+                get_params:"<?php echo GET_PARAMS; ?>",
+                permissions:{
+                    dir:{
+                        ed:<?php echo $kfm_allow_directory_edit; ?>,
+                        mk:<?php echo $kfm_allow_directory_create; ?>,
+                        mv:<?php echo $kfm_allow_directory_move; ?>,
+                        rm:<?php echo $kfm_allow_directory_delete; ?>
+                    },
+                    file:{
+                        rm:<?php echo $kfm_allow_file_delete; ?>,
+                        ed:<?php echo $kfm_allow_file_edit; ?>,
+                        mk:<?php echo $kfm_allow_file_create; ?>,
+                        mv:<?php echo $kfm_allow_file_move; ?>
+                    },
+                    image:{
+                        manip:<?php echo $kfm_allow_image_manipulation; ?>
+                    }
+                },
+                root_folder_name:"<?php echo $kfm_root_folder_name; ?>",
+                root_folder_id:<?php echo $kfm_root_folder_id; ?>,
+                startupfolder_id:<?php echo $kfm_startupfolder_id; ?>,
+                startup_sequence:<?php echo $startup_sequence; ?>,
+                                                               startup_selectedFiles:[<?php echo join(',',$kfm_startup_selectedFiles); ?>],
+                show_disabled_contextmenu_links:<?php echo $kfm_show_disabled_contextmenu_links; ?>,
+                use_multiple_file_upload:<?php echo $kfm_use_multiple_file_upload; ?>,
+                use_templates:<?php echo $templated; ?>,
+                version:'<?php echo KFM_VERSION; ?>'
+            };
+            var kfm_widgets=[];
+            function kfm_addWidget(obj){
+                kfm_widgets.push(obj);
+            }
+        </script>
+<?php // }}} ?>
+        <script type="text/javascript" src="j/all.php"></script>
+        <script type="text/javascript" src="j/hooks.js"></script>
+        <script type="text/javascript" src="lang/<?php echo $kfm_language; ?>.js"></script>
+<?php // {{{ widgets and plugins
+// {{{ include widgets if they exist
+$h = opendir(KFM_BASE_PATH.'widgets');
+while (false!==($dir = readdir($h))) {
+    if ($dir[0]!='.'&&is_dir(KFM_BASE_PATH.'widgets/'.$dir)) {
+        echo '         <script type="text/javascript" src="widgets/'.$dir.'/widget.js"></script>'."\n";
+    }
+}
+// }}}
+// {{{ show plugins if they exist
+foreach ($plugins as $plugin) {
+    if(file_exists(KFM_BASE_PATH.'plugins/'.$plugin.'/plugin.php')) include KFM_BASE_PATH.'plugins/'.$plugin.'/plugin.php';
+    if(file_exists(KFM_BASE_PATH.'plugins/'.$plugin.'/plugin.js'))echo '               <script type="text/javascript" src="plugins/'.$plugin.'/plugin.js"></script>'."\n";
+}
+// }}}
+// }}} ?>
+        <script type="text/javascript" src="j/swfupload-2.1.0b2/swfupload.js"></script>
+        <script type="text/javascript" src="j/swfupload-2.1.0b2/swfupload.swfobject.js"></script>
+<?php // {{{ more JavaScript environment variables. These should be merged into the above set whenever possible ?>
+        <script type="text/javascript">
+            var phpsession = "<?php echo session_id(); ?>";
+            var session_key="<?php echo $kfm_session->key; ?>";
+            var starttype="<?php echo isset($_GET['type'])?$_GET['type']:''; ?>";
+            var fckroot="<?php echo $kfm_userfiles_address; ?>";
+            var fckrootOutput="<?php echo $kfm_userfiles_output; ?>";
+            var kfm_file_handler="<?php echo $kfm_file_handler; ?>";
+            var kfm_log_level=<?php echo $kfm_log_level; ?>;
+            var kfm_return_directory=<?php echo isset($_GET['return_directory'])?'1':'0'; ?>;
+            var kfm_theme="<?php echo $kfm_theme; ?>";
+            var kfm_hidden_panels="<?php echo $kfm_hidden_panels; ?>".split(',');
+            var kfm_show_files_in_groups_of=<?php echo $kfm_show_files_in_groups_of; ?>;
+            var kfm_slideshow_delay=<?php echo ((int)$kfm_slideshow_delay)*1000; ?>;
+            var kfm_listview=<?php echo $kfm_listview;?>;
+            var kfm_startup_sequence_index = 0;
+            var kfm_cwd_id=<?php echo $kfm_startupfolder_id; ?>;
+            for(var i = 0;i<kfm_hidden_panels.length;++i)kfm_hidden_panels[i] = 'kfm_'+kfm_hidden_panels[i]+'_panel';
+            <?php echo kfm_kaejax_get_javascript(); ?>
+            <?php if(isset($_GET['kfm_caller_type']))echo 'window.kfm_caller_type="'.addslashes($_GET['kfm_caller_type']).'";'; ?>
+            var editable_extensions=["<?php echo join('","', $kfm_editable_extensions);?>"];
+            var viewable_extensions=["<?php echo join('","', $kfm_viewable_extensions);?>"];
+        </script>
+<?php // }}} ?>
+    </body>
+</html>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/initialise.php b/ipf/admin/media/tiny_mce/plugins/kfm/initialise.php
new file mode 100755 (executable)
index 0000000..bbf7653
--- /dev/null
@@ -0,0 +1,569 @@
+<?php
+/**
+ * KFM - Kae's File Manager - initialisation
+ *
+ * @category None
+ * @package  None
+ * @author   Kae Verens <kae@verens.com>
+ * @author   Benjamin ter Kuile <bterkuile@gmail.com>
+ * @license  docs/license.txt for licensing
+ * @link     http://kfm.verens.com/
+ */
+define('KFM_BASE_PATH', dirname(__FILE__).'/');
+
+// {{{ load classes and helper functions
+require KFM_BASE_PATH.'includes/lang.php';
+require KFM_BASE_PATH.'includes/db.php';
+require KFM_BASE_PATH.'includes/object.class.php';
+require KFM_BASE_PATH.'includes/kfm.class.php';
+require KFM_BASE_PATH.'includes/session.class.php';
+require KFM_BASE_PATH.'includes/file.class.php';
+require KFM_BASE_PATH.'includes/image.class.php';
+require KFM_BASE_PATH.'includes/directory.class.php';
+// }}}
+function sql_escape($sql)
+{
+    global $kfm_db_type;
+    $sql = addslashes($sql);
+    if ($kfm_db_type=='sqlite'||$kfm_db_type=='sqlitepdo')$sql = str_replace("\\'", "''", $sql);
+    return $sql;
+}
+function kfm_dieOnError($error)
+{
+    if (!PEAR::isError($error))return;
+    echo '<strong>Error</strong><br />'.$error->getMessage().'<br />'.$error->userinfo.'<hr />';
+    exit;
+}
+
+if (get_magic_quotes_gpc()) {
+    // taken from http://www.phpfreaks.com/quickcode/Get-rid-of-magic_quotes_gpc/618.php
+    function traverse (&$arr)
+    {
+        if (!is_array($arr))return;
+        foreach ($arr as $key=>$val) {
+            if (is_array($arr[$key])) traverse($arr[$key]);
+            else $arr[$key] = stripslashes($arr[$key]);
+        }
+    }
+    $gpc = array(&$_GET,&$_POST,&$_COOKIE);
+    traverse($gpc);
+}
+set_include_path(KFM_BASE_PATH.'includes/pear'.PATH_SEPARATOR.get_include_path());
+if (!file_exists(KFM_BASE_PATH.'configuration.php')) {
+    echo '<em>Missing <code>configuration.php</code>!</em><p>If this is a fresh installation of KFM, then please copy <code>configuration.dist.php</code> to <code>configuration.php</code>, remove the settings you don\'t want to change, and edit the rest to your needs.</p><p>For examples of configuration, please visit http://kfm.verens.com/configuration</p>';
+    exit;
+}
+require_once KFM_BASE_PATH.'configuration.dist.php';
+require_once KFM_BASE_PATH.'configuration.php';
+// {{{ defines
+define('KFM_DB_PREFIX', $kfm_db_prefix);
+// }}}
+
+// {{{ check for fatal errors
+$m = array();
+if (ini_get('safe_mode'))$m[] = 'KFM does not work if you have <code>safe_mode</code> enabled. This is not a bug - please see <a href="http://ie.php.net/features.safe-mode">PHP.net\'s safe_mode page</a> for details';
+if (!isset($kfm_allow_directory_create))$m[] = 'missing <code>$kfm_allow_directory_create</code> variable';
+if (!isset($kfm_allow_directory_delete))$m[] = 'missing <code>$kfm_allow_directory_delete</code> variable';
+if (!isset($kfm_allow_directory_edit))$m[] = 'missing <code>$kfm_allow_directory_edit</code> variable';
+if (!isset($kfm_allow_directory_move))$m[] = 'missing <code>$kfm_allow_directory_move</code> variable';
+if (!isset($kfm_allow_file_create))$m[] = 'missing <code>$kfm_allow_file_create</code> variable';
+if (!isset($kfm_allow_file_delete))$m[] = 'missing <code>$kfm_allow_file_delete</code> variable';
+if (!isset($kfm_allow_file_edit))$m[] = 'missing <code>$kfm_allow_file_edit</code> variable';
+if (!isset($kfm_allow_file_move))$m[] = 'missing <code>$kfm_allow_file_move</code> variable';
+if (!isset($kfm_allow_file_upload))$m[] = 'missing <code>$kfm_allow_file_upload</code> variable';
+if (!isset($kfm_allow_image_manipulation))$m[] = 'missing <code>$kfm_allow_image_manipulation</code> variable';
+if (!isset($kfm_only_allow_image_upload))$m[] = 'missing <code>$kfm_only_allow_image_upload</code> variable';
+if (!isset($kfm_show_disabled_contextmenu_links))$m[] = 'missing <code>$kfm_show_disabled_contextmenu_links</code> variable';
+if (!isset($kfm_use_multiple_file_upload))$m[] = 'missing <code>$kfm_use_multiple_file_upload</code> variable';
+if (!isset($kfm_use_imagemagick))$m[] = 'missing <code>$kfm_use_imagemagick</code> variable';
+if (!isset($kfm_slideshow_delay))$m[] = 'missing <code>$kfm_slideshow_delay</code> variable';
+if (!isset($kfm_db_port))$m[] = 'missing <code>$kfm_db_port</code> variable';
+if (!isset($kfm_root_folder_name))$m[] = 'missing <code>$kfm_root_folder_name</code> variable';
+if (!isset($kfm_files_name_length_displayed))$m[] = 'missing <code>$kfm_files_name_length_displayed</code> variable';
+if (!isset($kfm_default_upload_permission))$m[] = 'missing <code>$kfm_default_upload_permission</code> variable';
+if (!isset($kfm_return_file_id_to_cms))$m[] = 'missing <code>$kfm_return_file_id_to_cms</code> variable';
+if (!isset($kfm_listview))$m[] = 'missing <code>$kfm_listview</code> variable';
+if (!isset($kfm_allow_multiple_file_returns))$m[] = 'missing <code>$kfm_allow_multiple_file_returns</code> variable';
+if (!isset($kfm_userfiles_address))$m[] = 'missing <code>$kfm_userfiles_address</code> variable. this variable replaces the old <code>$kfm_userfiles</code> variable. <strong>Please read the examples carefully.</strong>';
+if (!isset($kfm_banned_files))$m[] = 'missing <code>$kfm_banned_files</code> variable';
+if (!isset($kfm_banned_folders))$m[] = 'missing <code>$kfm_banned_folders</code> variable';
+if (count($m)) {
+    echo '<html><body><p>There are errors in your configuration or server. If the messages below describe missing variables, please check the supplied <code>configuration.php.dist</code> for notes on their usage.</p><ul>';
+    foreach($m as $a)echo '<li>'.$a.'</li>';
+    echo '</li></ul></body></html>';
+    exit;
+}
+// }}}
+
+// {{{ API - for programmers only
+if (file_exists(KFM_BASE_PATH.'api/config.php')) require KFM_BASE_PATH.'api/config.php';
+if (file_exists(KFM_BASE_PATH.'api/cms_hooks.php')) require KFM_BASE_PATH.'api/cms_hooks.php';
+else require KFM_BASE_PATH.'api/cms_hooks.php.dist';
+// }}}
+// {{{ variables
+$kfm->defaultSetting('time_format', '%T');
+$kfm->setting('db_prefix', $kfm_db_prefix);
+if (isset($kfm_date_format)) {
+    $kfm->setting('date_format', $kfm_date_format);
+    unset($kfm_date_format);
+} else {
+    $kfm->defaultSetting('db_prefix', 'kfm_');
+}
+if (isset($kfm_time_format)) {
+    $kfm->setting('time_format', $kfm_time_format);
+    unset($kfm_time_format);
+} else {
+    $kfm->defaultSetting('date_format', '%d-%m-%Y');
+}
+
+if (!isset($kfm_show_files_in_groups_of))$kfm_show_files_in_groups_of = 10;
+if (!isset($kfm_user_root_folder))$kfm_user_root_folder = false;
+if (!isset($kfm_startup_folder))$kfm_startup_folder = false;
+if (!isset($kfm_startup_selectedFiles))$kfm_startup_selectedFiles = array();
+define('KFM_VERSION', rtrim(file_get_contents(KFM_BASE_PATH.'docs/version.txt')));
+if (!isset($_SERVER['DOCUMENT_ROOT'])) { // fix for IIS
+    $_SERVER['DOCUMENT_ROOT'] = preg_replace('/\/[^\/]*$/', '', str_replace('\\', '/', $_SERVER['SCRIPT_FILENAME']));
+}
+$rootdir = strpos($kfm_userfiles_address, './')===0?KFM_BASE_PATH.$kfm_userfiles_address:$kfm_userfiles_address.'/';
+if (!is_dir($rootdir))mkdir($rootdir, 0755);
+if (!is_dir($rootdir)) {
+    echo 'error: "'.htmlspecialchars($rootdir).'" could not be created';
+    exit;
+}
+$rootdir = realpath($rootdir).'/';
+define('KFM_DIR', dirname(__FILE__));
+if (!defined('GET_PARAMS')) define('GET_PARAMS', '');
+define('IMAGEMAGICK_PATH', isset($kfm_imagemagick_path)?$kfm_imagemagick_path:'/usr/bin/convert');
+$cache_directories = array();
+$kfm_errors        = array();
+$kfm_messages      = array();
+// }}}
+// {{{ work directory
+if ($kfm_workdirectory[0]=='/') {
+    $workpath = $kfm_workdirectory;
+} else {
+    $workpath = $rootdir.$kfm_workdirectory;
+}
+$workurl = $kfm_userfiles_output.$kfm_workdirectory;
+$workdir = true;
+if (substr($workpath, -1)!='/') $workpath.='/';
+if (substr($workurl, -1)!='/') $workurl.='/';
+define('WORKPATH', $workpath);
+define('WORKURL', $workurl);
+if (is_dir($workpath)) {
+    if (!is_writable($workpath)) {
+        echo 'error: "'.htmlspecialchars($workpath).'" is not writable';
+        exit;
+    }
+} else {
+    // Support for creating the directory
+    $workpath_tmp = substr($workpath, 0, -1);
+    if (is_writable(dirname($workpath_tmp)))mkdir($workpath_tmp, 0755);
+    else{
+        echo 'error: could not create directory <code>"'.htmlspecialchars($workpath_tmp).'"</code>. please make sure that <code>'.htmlspecialchars(preg_replace('#/[^/]*$#', '', $workpath_tmp)).'</code> is writable by the server';
+        exit;
+    }
+}
+// }}}
+// {{{ database
+$db_defined            = 0;
+$kfm_db_prefix_escaped = str_replace('_', '\\\\_', KFM_DB_PREFIX);
+$port                  = ($kfm_db_port=='')?'':':'.$kfm_db_port;
+switch($kfm_db_type) {
+case 'mysql': // {{{
+    include_once 'MDB2.php';
+    $dsn   = 'mysql://'.$kfm_db_username.':'.$kfm_db_password.'@'.$kfm_db_host.$port.'/'.$kfm_db_name;
+    $kfmdb = &MDB2::connect($dsn);
+    if (PEAR::isError($kfmdb)) {
+        $dsn   = 'mysql://'.$kfm_db_username.':'.$kfm_db_password.'@'.$kfm_db_host;
+        $kfmdb = &MDB2::connect($dsn);
+        kfm_dieOnError($kfmdb);
+        $kfmdb->query('CREATE DATABASE '.$kfm_db_name.' CHARACTER SET UTF8');
+        $kfmdb->disconnect();
+        $dsn   = 'mysql://'.$kfm_db_username.':'.$kfm_db_password.'@'.$kfm_db_host.'/'.$kfm_db_name;
+        $kfmdb = &MDB2::connect($dsn);
+        kfm_dieOnError($kfmdb);
+    }
+    $kfmdb->setFetchMode(MDB2_FETCHMODE_ASSOC);
+    if (!$db_defined) {
+        $res = &$kfmdb->query("show tables like '".$kfm_db_prefix_escaped."%'");
+        kfm_dieOnError($res);
+        if (!$res->numRows())include KFM_BASE_PATH.'scripts/db.mysql.create.php';
+        else $db_defined = 1;
+    }
+    break;
+// }}}
+case 'pgsql': // {{{
+    include_once 'MDB2.php';
+    $dsn   = 'pgsql://'.$kfm_db_username.':'.$kfm_db_password.'@'.$kfm_db_host.$port.'/'.$kfm_db_name;
+    $kfmdb = &MDB2::connect($dsn);
+    if (PEAR::isError($kfmdb)) {
+        $dsn   = 'pgsql://'.$kfm_db_username.':'.$kfm_db_password.'@'.$kfm_db_host;
+        $kfmdb = &MDB2::connect($dsn);
+        kfm_dieOnError($kfmdb);
+        $kfmdb->query('CREATE DATABASE '.$kfm_db_name);
+        $kfmdb->disconnect();
+        $dsn   = 'pgsql://'.$kfm_db_username.':'.$kfm_db_password.'@'.$kfm_db_host.'/'.$kfm_db_name;
+        $kfmdb = &MDB2::connect($dsn);
+        kfm_dieOnError($kfmdb);
+    }
+    $kfmdb->setFetchMode(MDB2_FETCHMODE_ASSOC);
+    if (!$db_defined) {
+        $res = &$kfmdb->query("SELECT tablename from pg_tables where tableowner = current_user AND tablename NOT LIKE E'pg\\\\_%' AND tablename NOT LIKE E'sql\\\\_%' AND tablename LIKE E'".$kfm_db_prefix_escaped."%'");
+        kfm_dieOnError($res);
+        if ($res->numRows()<1)include KFM_BASE_PATH.'scripts/db.pgsql.create.php';
+        else $db_defined = 1;
+    }
+    break;
+// }}}
+case 'sqlite': // {{{
+    include_once 'MDB2.php';
+    $kfmdb_create = false;
+    define('DBNAME', $kfm_db_name);
+    if (!file_exists(WORKPATH.DBNAME))$kfmdb_create = true;
+    $dsn   = array('phptype'=>'sqlite', 'database'=>WORKPATH.DBNAME, 'mode'=>'0644');
+    $kfmdb = &MDB2::connect($dsn);
+    kfm_dieOnError($kfmdb);
+    $kfmdb->setFetchMode(MDB2_FETCHMODE_ASSOC);
+    if ($kfmdb_create)include KFM_BASE_PATH.'scripts/db.sqlite.create.php';
+    $db_defined = 1;
+    break;
+// }}}
+case 'sqlitepdo': // {{{
+    $kfmdb_create = false;
+    define('DBNAME', $kfm_db_name);
+    if (!file_exists(WORKPATH.DBNAME)) $kfmdb_create = true;
+    $dsn   = array('type'=>'sqlitepdo', 'database'=>WORKPATH.DBNAME, 'mode'=>'0644');
+    $kfmdb = new DB($dsn);
+    if ($kfmdb_create)include KFM_BASE_PATH.'scripts/db.sqlite.create.php';
+    $db_defined = 1;
+    break;
+// }}}
+default: // {{{
+    echo "unknown database type specified ($kfm_db_type)";
+    exit;
+    // }}}
+}
+if (!$db_defined) {
+    echo 'failed to connect to database';
+    exit;
+}
+$kfm->db = &$kfmdb; // Add database as reference to the kfm object
+// }}}
+// {{{ get kfm parameters and check for updates
+$kfm_parameters = array();
+$rs = db_fetch_all("select * from ".KFM_DB_PREFIX."parameters");
+foreach($rs as $r)$kfm_parameters[$r['name']] = $r['value'];
+if ($kfm_parameters['version']!=KFM_VERSION && file_exists(KFM_BASE_PATH.'scripts/update.'.KFM_VERSION.'.php')) require KFM_BASE_PATH.'scripts/update.'.KFM_VERSION.'.php';
+// }}}
+// {{{ JSON
+if (!function_exists('json_encode')) { // php-json is not installed
+    include_once 'JSON.php';
+    include_once KFM_BASE_PATH.'includes/json.php';
+}
+// }}}
+// {{{ start session
+$session_id  = (isset($_GET['kfm_session']))?$_GET['kfm_session']:'';
+$kfm_session = new kfmSession($session_id);
+if ($kfm_session->isNew) {
+    $kfm_session->setMultiple(array(
+    'cwd_id'=>1,
+    'language'=>'',
+    'username'=>'',
+    'password'=>'',
+    'loggedin'=>0,
+    'theme'=>$kfm_theme
+    ));
+}
+if (isset($_GET['theme']))$kfm_session->set('theme', $_GET['theme']);
+if (isset($_GET['logout'])||isset($_GET['log_out'])) $kfm_session->set('loggedin',0);
+$kt = $kfm_session->get('theme');
+if ($kt)$kfm_theme = $kt;
+else $kfm_session->set('theme', $kfm_theme);
+// }}}
+// {{{ check authentication
+if (!isset($kfm_username)||!isset($kfm_password)||($kfm_username==''&&$kfm_password==''))$kfm_session->set('loggedin', 1);
+if (!$kfm_session->get('loggedin') && (!isset($kfm_api_auth_override)||!$kfm_api_auth_override)) {
+    $err = '';
+    if (isset($_POST['username'])&&isset($_POST['password'])) {
+        if ($_POST['username']==$kfm_username && $_POST['password']==$kfm_password) {
+            $kfm_session->setMultiple(array('username'=>$_POST['username'], 'password'=>$_POST['password'], 'loggedin'=>1));
+        }
+        else $err = '<em>Incorrect Password. Please try again, or check your <code>configuration.php</code>.</em>';
+    }
+    if (!$kfm_session->get('loggedin')) {
+        include KFM_BASE_PATH.'includes/login.php';
+        exit;
+    }
+}
+// }}}
+// {{{ languages
+$kfm_language = '';
+// {{{  find available languages
+if ($handle = opendir(KFM_BASE_PATH.'lang')) {
+    $files = array();
+    while(false!==($file = readdir($handle)))if (is_file(KFM_BASE_PATH.'lang/'.$file))$files[] = $file;
+    closedir($handle);
+    sort($files);
+    $kfm_available_languages = array();
+    foreach($files as $f)$kfm_available_languages[] = str_replace('.js', '', $f);
+} else {
+    echo 'error: missing language files';
+    exit;
+}
+// }}}
+// {{{  check for URL parameter "lang"
+if (isset($_GET['lang'])&&$_GET['lang']&&in_array($_GET['lang'], $kfm_available_languages)) {
+    $kfm_language = $_GET['lang'];
+    $kfm_session->set('language', $kfm_language);
+}
+// }}}
+// {{{  check session for language selected earlier
+    if (
+        $kfm_language==''&&
+        !is_null($kfm_session->get('language'))&&
+        $kfm_session->get('language')!=''&&
+        in_array($kfm_session->get('language'), $kfm_available_languages)
+    )$kfm_language = $kfm_session->get('language');
+// }}}
+// {{{  check the browser's http headers for preferred languages
+if ($kfm_language=='') {
+    if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))$_SERVER['HTTP_ACCEPT_LANGUAGE'] = '';
+    $langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
+    foreach($langs as $lang)if (in_array(preg_replace('/;.*/','',trim($lang)), $kfm_available_languages)) {
+        $kfm_language = preg_replace('/;.*/','',trim($lang));
+        break;
+    }
+}
+// }}}
+// {{{  check the kfm_preferred_languages
+if ($kfm_language=='')foreach($kfm_preferred_languages as $lang)if (in_array($lang, $kfm_available_languages)) {
+    $kfm_language = $lang;
+    break;
+}
+// }}}
+// {{{  still no language chosen? use the first available one then
+    if ($kfm_language=='')$kfm_language = $kfm_available_languages[0];
+// }}}
+// }}}
+// {{{ make a few corrections to the config where necessary
+foreach($kfm_editable_extensions as $v)if (!in_array($v, $kfm_viewable_extensions))$kfm_viewable_extensions[] = $v;
+// }}}
+// {{{ common functions
+function kfm_checkAddr($filename='')
+{
+    if(
+        $filename=='' || 
+        preg_match('#^ |^\.|\.$| $|\.\.|/\.#',$filename)
+    )return false;
+    $exts=explode('.',$filename);
+    for($i=1;$i<count($exts);++$i){
+        $ext=$exts[$i];
+        if(in_array($ext,$GLOBALS['kfm_banned_extensions']))return false;
+    }
+               return true;
+}
+function get_mimetype($f)
+{
+    $mimetypes = array('ez'=>'application/andrew-inset', 'hqx'=>'application/mac-binhex40', 'cpt'=>'application/mac-compactpro', 'doc'=>'application/msword', 'bin'=>'application/octet-stream', 'dms'=>'application/octet-stream', 'lha'=>'application/octet-stream', 'lzh'=>'application/octet-stream', 'exe'=>'application/octet-stream', 'class'=>'application/octet-stream', 'so'=>'application/octet-stream', 'dll'=>'application/octet-stream', 'oda'=>'application/oda', 'pdf'=>'application/pdf', 'ai'=>'application/postscript', 'eps'=>'application/postscript', 'ps'=>'application/postscript', 'smi'=>'application/smil', 'smil'=>'application/smil', 'mif'=>'application/vnd.mif', 'xls'=>'application/vnd.ms-excel', 'ppt'=>'application/vnd.ms-powerpoint', 'wbxml'=>'application/vnd.wap.wbxml', 'wmlc'=>'application/vnd.wap.wmlc', 'wmlsc'=>'application/vnd.wap.wmlscriptc', 'bcpio'=>'application/x-bcpio', 'vcd'=>'application/x-cdlink', 'pgn'=>'application/x-chess-pgn', 'cpio'=>'application/x-cpio', 'csh'=>'application/x-csh', 'dcr'=>'application/x-director', 'dir'=>'application/x-director', 'dxr'=>'application/x-director', 'dvi'=>'application/x-dvi', 'spl'=>'application/x-futuresplash', 'gtar'=>'application/x-gtar', 'hdf'=>'application/x-hdf', 'js'=>'application/x-javascript', 'skp'=>'application/x-koan', 'skd'=>'application/x-koan', 'skt'=>'application/x-koan', 'skm'=>'application/x-koan', 'latex'=>'application/x-latex', 'nc'=>'application/x-netcdf', 'cdf'=>'application/x-netcdf', 'sh'=>'application/x-sh', 'shar'=>'application/x-shar', 'swf'=>'application/x-shockwave-flash', 'sit'=>'application/x-stuffit', 'sv4cpio'=>'application/x-sv4cpio', 'sv4crc'=>'application/x-sv4crc', 'tar'=>'application/x-tar', 'tcl'=>'application/x-tcl', 'tex'=>'application/x-tex', 'texinfo'=>'application/x-texinfo', 'texi'=>'application/x-texinfo', 't'=>'application/x-troff', 'tr'=>'application/x-troff', 'roff'=>'application/x-troff', 'man'=>'application/x-troff-man', 'me'=>'application/x-troff-me', 'ms'=>'application/x-troff-ms', 'ustar'=>'application/x-ustar', 'src'=>'application/x-wais-source', 'xhtml'=>'application/xhtml+xml', 'xht'=>'application/xhtml+xml', 'zip'=>'application/zip', 'au'=>'audio/basic', 'snd'=>'audio/basic', 'mid'=>'audio/midi', 'midi'=>'audio/midi', 'kar'=>'audio/midi', 'mpga'=>'audio/mpeg', 'mp2'=>'audio/mpeg', 'mp3'=>'audio/mpeg', 'aif'=>'audio/x-aiff', 'aiff'=>'audio/x-aiff', 'aifc'=>'audio/x-aiff', 'm3u'=>'audio/x-mpegurl', 'ram'=>'audio/x-pn-realaudio', 'rm'=>'audio/x-pn-realaudio', 'rpm'=>'audio/x-pn-realaudio-plugin', 'ra'=>'audio/x-realaudio', 'wav'=>'audio/x-wav', 'pdb'=>'chemical/x-pdb', 'xyz'=>'chemical/x-xyz', 'bmp'=>'image/bmp', 'gif'=>'image/gif', 'ief'=>'image/ief', 'jpeg'=>'image/jpeg', 'jpg'=>'image/jpeg', 'jpe'=>'image/jpeg', 'png'=>'image/png', 'tiff'=>'image/tiff', 'tif'=>'image/tiff', 'djvu'=>'image/vnd.djvu', 'djv'=>'image/vnd.djvu', 'wbmp'=>'image/vnd.wap.wbmp', 'ras'=>'image/x-cmu-raster', 'pnm'=>'image/x-portable-anymap', 'pbm'=>'image/x-portable-bitmap', 'pgm'=>'image/x-portable-graymap', 'ppm'=>'image/x-portable-pixmap', 'rgb'=>'image/x-rgb', 'xbm'=>'image/x-xbitmap', 'xpm'=>'image/x-xpixmap', 'xwd'=>'image/x-xwindowdump', 'igs'=>'model/iges', 'iges'=>'model/iges', 'msh'=>'model/mesh', 'mesh'=>'model/mesh', 'silo'=>'model/mesh', 'wrl'=>'model/vrml', 'vrml'=>'model/vrml', 'css'=>'text/css', 'html'=>'text/html', 'htm'=>'text/html', 'asc'=>'text/plain', 'txt'=>'text/plain', 'rtx'=>'text/richtext', 'rtf'=>'text/rtf', 'sgml'=>'text/sgml', 'sgm'=>'text/sgml', 'tsv'=>'text/tab-separated-values', 'wml'=>'text/vnd.wap.wml', 'wmls'=>'text/vnd.wap.wmlscript', 'etx'=>'text/x-setext', 'xsl'=>'text/xml', 'xml'=>'text/xml', 'mpeg'=>'video/mpeg', 'mpg'=>'video/mpeg', 'mpe'=>'video/mpeg', 'qt'=>'video/quicktime', 'mov'=>'video/quicktime', 'mxu'=>'video/vnd.mpegurl', 'avi'=>'video/x-msvideo', 'movie'=>'video/x-sgi-movie', 'ice'=>'x-conference/x-cooltalk');
+    $extension = preg_replace('/.*\./', '', $f);
+    if (isset($mimetypes[$extension]))return $mimetypes[$extension];
+    return 'unknown/mimetype';
+}
+// }}}
+// {{{ directory functions
+function kfm_add_directory_to_db($name, $parent)
+{
+    include_once KFM_BASE_PATH.'includes/directories.php';
+    return _add_directory_to_db($name, $parent);
+}
+function kfm_createDirectory($parent, $name)
+{
+    include_once KFM_BASE_PATH.'includes/directories.php';
+    return _createDirectory($parent, $name);
+}
+function kfm_deleteDirectory($id, $recursive = 0)
+{
+    include_once KFM_BASE_PATH.'includes/directories.php';
+    return _deleteDirectory($id, $recursive);
+}
+function kfm_getDirectoryDbInfo($id)
+{
+    include_once KFM_BASE_PATH.'includes/directories.php';
+    return _getDirectoryDbInfo($id);
+}
+function kfm_getDirectoryParents($pid, $type = 1)
+{
+    include_once KFM_BASE_PATH.'includes/directories.php';
+    return _getDirectoryParents($pid, $type);
+}
+function kfm_getDirectoryParentsArr($pid, $path = array())
+{
+    include_once KFM_BASE_PATH.'includes/directories.php';
+    return _getDirectoryParentsArr($pid, $path);
+}
+function kfm_loadDirectories($root, $oldpid = 0)
+{
+    include_once KFM_BASE_PATH.'includes/directories.php';
+    return _loadDirectories($root, $oldpid);
+}
+function kfm_moveDirectory($from, $to)
+{
+    include_once KFM_BASE_PATH.'includes/directories.php';
+    return _moveDirectory($from, $to);
+}
+function kfm_renameDirectory($dir, $newname)
+{
+    include_once KFM_BASE_PATH.'includes/directories.php';
+    return _renameDirectory($dir, $newname);
+}
+function kfm_rmdir($dir)
+{
+    include_once KFM_BASE_PATH.'includes/directories.php';
+    return _rmdir($dir);
+}
+// }}}
+// {{{ file functions
+function kfm_copyFiles($files, $dir_id)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _copyFiles($files, $dir_id);
+}
+function kfm_createEmptyFile($cwd, $filename)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _createEmptyFile($cwd, $filename);
+}
+function kfm_downloadFileFromUrl($url, $filename)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _downloadFileFromUrl($url, $filename);
+}
+function kfm_extractZippedFile($id)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _extractZippedFile($id);
+}
+function kfm_getFileAsArray($filename)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _getFileAsArray($filename);
+}
+function kfm_getFileDetails($filename)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _getFileDetails($filename);
+}
+function kfm_getFileUrl($fid, $x = 0, $y = 0)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _getFileUrl($fid, $x, $y);
+}
+function kfm_getFileUrls($farr)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _getFileUrls($farr);
+}
+function kfm_getTagName($id)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _getTagName($id);
+}
+function kfm_getTextFile($filename)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _getTextFile($filename);
+}
+function kfm_moveFiles($files, $dir_id)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _moveFiles($files, $dir_id);
+}
+function kfm_loadFiles($rootid = 1, $setParent = false)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _loadFiles($rootid, $setParent);
+}
+function kfm_renameFile($filename, $newfilename)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _renameFile($filename, $newfilename);
+}
+function kfm_renameFiles($files, $template)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _renameFiles($files, $template);
+}
+function kfm_resize_bytes($size)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _resize_bytes($size);
+}
+function kfm_rm($files, $no_dir = 0)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _rm($files, $no_dir);
+}
+function kfm_saveTextFile($filename, $text)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _saveTextFile($filename, $text);
+}
+function kfm_search($keywords, $tags)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _search($keywords, $tags);
+}
+function kfm_tagAdd($recipients, $tagList)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _tagAdd($recipients, $tagList);
+}
+function kfm_tagRemove($recipients, $tagList)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _tagRemove($recipients, $tagList);
+}
+function kfm_zip($name, $files)
+{
+    include_once KFM_BASE_PATH.'includes/files.php';
+    return _zip($name, $files);
+}
+// }}}
+// {{{ image functions
+function kfm_changeCaption($filename, $newCaption)
+{
+    include_once KFM_BASE_PATH.'includes/images.php';
+    return _changeCaption($filename, $newCaption);
+}
+function kfm_getThumbnail($fileid, $width, $height)
+{
+    include_once KFM_BASE_PATH.'includes/images.php';
+    return _getThumbnail($fileid, $width, $height);
+}
+function kfm_resizeImage($filename, $width, $height)
+{
+    include_once KFM_BASE_PATH.'includes/images.php';
+    return _resizeImage($filename, $width, $height);
+}
+function kfm_resizeImages($files, $width, $height)
+{
+    include_once KFM_BASE_PATH.'includes/images.php';
+    return _resizeImages($files, $width, $height);
+}
+function kfm_rotateImage($filename, $direction)
+{
+    include_once KFM_BASE_PATH.'includes/images.php';
+    return _rotateImage($filename, $direction);
+}
+function kfm_cropToOriginal($fid, $x1, $y1, $width, $height)
+{
+    include_once KFM_BASE_PATH.'includes/images.php';
+    return _cropToOriginal($fid, $x1, $y1, $width, $height);
+}
+function kfm_cropToNew($fid, $x1, $y1, $width, $height, $newname)
+{
+    include_once KFM_BASE_PATH.'includes/images.php';
+    return _cropToNew($fid, $x1, $y1, $width, $height, $newname);
+}
+// }}}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/alerts.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/alerts.js
new file mode 100644 (file)
index 0000000..9b68ff9
--- /dev/null
@@ -0,0 +1,4 @@
+// see license.txt for licensing
+function kfm_showMessage(message){
+       new Notice(message);
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/all.php b/ipf/admin/media/tiny_mce/plugins/kfm/j/all.php
new file mode 100644 (file)
index 0000000..f999491
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+$js='';
+$js.=file_get_contents('variables.js');
+$js.=file_get_contents('notice.js');
+$js.=file_get_contents('kfm.js');
+$js.=file_get_contents('alerts.js');
+$js.=file_get_contents('modal.dialog.js');
+$js.=file_get_contents('contextmenu.js');
+$js.=file_get_contents('directories.js');
+$js.=file_get_contents('file.selections.js');
+$js.=file_get_contents('file.text-editing.js');
+$js.=file_get_contents('images.and.icons.js');
+$js.=file_get_contents('panels.js');
+$js.=file_get_contents('tags.js');
+$js.=file_get_contents('common.js');
+$js.=file_get_contents('kaejax_replaces.js');
+$js.=file_get_contents('kdnd.js');
+$js.=file_get_contents('file.class.js');
+$js.=file_get_contents('files.js');
+$js.=file_get_contents('resize_handler.js');
+$js.=file_get_contents('search.js');
+header('Content-type: text/javascript');
+header('Expires: '.gmdate("D, d M Y H:i:s", time() + 3600*24*365).' GMT');
+echo $js;
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/browser-specific.ie.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/browser-specific.ie.js
new file mode 100644 (file)
index 0000000..64e3cdb
--- /dev/null
@@ -0,0 +1,12 @@
+// see ../license.txt for licensing
+function clearSelections(){
+       document.selection.empty();
+}
+function getWindowScrollAt(){
+       var d=document.body;
+       if(d.scrollLeft||d.scrollTop){
+               return {x:d.scrollLeft,y:d.scrollTop};
+       }
+       d=document.documentElement;
+       return {x:d.scrollLeft,y:d.scrollTop};
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/browser-specific.konqueror.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/browser-specific.konqueror.js
new file mode 100644 (file)
index 0000000..40fe89d
--- /dev/null
@@ -0,0 +1,4 @@
+// see license.txt for licensing
+function clearSelections(e){
+// not possible yet
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/common.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/common.js
new file mode 100644 (file)
index 0000000..97f1471
--- /dev/null
@@ -0,0 +1,205 @@
+// see ../license.txt for licensing
+function clearSelections(){
+       window.getSelection().removeAllRanges();
+}
+function getOffset(el,s) {
+       if(!el){
+               return 0;
+       }
+       var n=parseInt(el['offset'+s],10),p=el.offsetParent;
+       if(p){
+               n+=getOffset(p,s)-parseInt(p['scroll'+s],10);
+       }
+       return n;
+}
+function getWindowScrollAt(){
+       return {x:window.pageXOffset,y:window.pageYOffset};
+}
+function kfm_kaejax_do_call(func_name,args){
+       var uri=function_urls[func_name];
+       if(!window.kfm_kaejax_timeouts[uri]){
+               window.kfm_kaejax_timeouts[uri]={t:setTimeout('kfm_kaejax_sendRequests("'+uri+'")',1),c:[],callbacks:[]};
+       }
+       var l=window.kfm_kaejax_timeouts[uri].c.length,v2=[];
+       for(var i=0;i<args.length-1;++i){
+               v2[v2.length]=args[i];
+       }
+       window.kfm_kaejax_timeouts[uri].c[l]={f:func_name,v:v2};
+       window.kfm_kaejax_timeouts[uri].callbacks[l]=args[args.length-1];
+}
+function kfm_kaejax_sendRequests(uri){
+       var t=window.kfm_kaejax_timeouts[uri],callbacks=window.kfm_kaejax_timeouts[uri].callbacks;
+       t.callbacks=null;
+       window.kfm_kaejax_timeouts[uri]=null;
+       var x=new XMLHttpRequest(),post_data="kaejax="+escape(Json.toString(t)).replace(kfm_regexps.plus,'%2B').replace(kfm_regexps.ascii_stuff,'%u00$1').replace(/\n/g,' ');
+       post_data=kfm_sanitise_ajax(post_data);
+       x.open('POST',uri,true);
+       x.setRequestHeader("Method","POST "+uri+" HTTP/1.1");
+       x.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
+       x.onreadystatechange=function(){
+               if(x.readyState!=4){
+                       return;
+               }
+               var r=x.responseText;
+               if(r.substring(0,5)=='error'){
+                       return kfm.alert(r);
+               }
+               var v=eval('('+unescape(r)+')');
+               var f,p,i;
+               if(v.errors.length)kfm.showErrors(v.errors);
+               if(v.messages.length)kfm.showMessages(v.messages);
+               for(i=0;i<t.c.length;++i){
+                       f=callbacks[i];
+                       p=[];
+                       if($type(f)=='array'){
+                               p=f;
+                               f=f[0];
+                       }
+                       f(v.results[i],p);
+               }
+       };
+       x.send(post_data);
+}
+function loadJS(url,id,lang,onload){
+       var i=0;
+       for(;i<loadedScripts.length;++i){
+               if(loadedScripts[i]==url){
+                       return 0;
+               }
+       }
+       loadedScripts.push(url);
+       var el=new Element('script',{
+               'type':'text/javascript'
+       });
+       if(id){
+               el.id=id;
+       }
+       if(lang){
+               el.lang=lang;
+       }
+       if(kfm_kaejax_is_loaded&&/\.php/.test(url)){
+               url+=(/\?/.test(url)?'&':'?')+'kfm_kaejax_is_loaded';
+       }
+       if(onload){
+               el.onload_triggered=0;
+               el.onload=function(){
+                       if(!this.onload_triggered++){
+                               eval(onload);
+                       }
+               };
+               el.onreadystatechange=function(){
+                       if(this.readyState=='loaded'||this.readyState=='complete'){
+                               if(!this.onload_triggered++){
+                                       eval(onload);
+                               }
+                       }
+               };
+       }
+       el.src=url;
+       $E('head').appendChild(el);
+       return 1;
+}
+function newForm(action,method,enctype,target){
+       if(window.ie)return $(document.createElement('<form action="'+action+'" method="'+method+'" enctype="'+enctype+'" target="'+target+'">'));
+       return new Element('form',{
+               'action':action,
+               'method':method,
+               'enctype':enctype,
+               'target':target
+       });
+}
+function newInput(n,t,v,cl){
+       var b;
+       if(!t){
+               t='text';
+       }
+       switch(t){
+               case 'checkbox':{
+                       b=new Element('input',{
+                               'id':n,
+                               'name':n,
+                               'type':'checkbox',
+                               'styles':{
+                                       'width':'auto'
+                               }
+                       });
+                       break;
+               }
+               case 'textarea':{
+                       b=new Element('textarea',{
+                               'id':n,
+                               'id':n
+                       });
+                       break;
+               }
+               default:{
+                       b=new Element('input',{
+                               'id':n,
+                               'name':n,
+                               'type':t
+                       });
+               }
+       }
+       if(v){
+               if(t=='checkbox'){
+                       $extend(b,{checked:'checked',defaultChecked:'checked'});
+               }
+               else if(t!='datetime'){
+                       b.value=v;
+               }
+       }
+       if(cl)b.className=cl;
+       return b;
+}
+function newLink(h,t,id,c,title){
+       if(!title){
+               title='';
+       }
+       return (new Element('a',{
+               'id':id,
+               'class':c,
+               'href':h,
+               'title':title
+       })).setHTML(t);
+}
+function newSelectbox(name,keys,vals,s,f){
+       var el2=new Element('select',{
+               'id':name
+       }),el3,s2=0,i=0;
+       if(!s){
+               s=0;
+       }
+       if(!vals){
+               vals=keys;
+       }
+       for(;i<vals.length;++i){
+               var v1=vals[i].toString();
+               var v2=v1.length>20?v1.substr(0,27)+'...':v1;
+               el3=(new Element('option',{
+                       value:keys[i],
+                       title:v1
+               })).setHTML(v2);
+               if(keys[i]==s){
+                       s2=i;
+               }
+               el2.appendChild(el3);
+       }
+       el2.selectedIndex=s2;
+       if(f){
+               el2.onchange=f;
+       }
+       return el2;
+}
+function newText(a){
+       return document.createTextNode(a);
+}
+if(window.ie){
+       XMLHttpRequest=function(){
+               var l=(ScriptEngineMajorVersion()>=5)?"Msxml2":"Microsoft";
+               return new ActiveXObject(l+".XMLHTTP")
+       }
+       loadJS('j/browser-specific.ie.js');
+}
+if(window.webkit){
+       loadJS('j/browser-specific.konqueror.js');
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/contextmenu.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/contextmenu.js
new file mode 100644 (file)
index 0000000..b0da16b
--- /dev/null
@@ -0,0 +1,97 @@
+// see license.txt for licensing
+function kfm_closeContextMenu(){
+       if(contextmenu)contextmenu.remove();
+       contextmenu=null;
+}
+function kfm_contextmenuinit(){
+       document.addEvent('click',function(e){
+               e=new Event(e);
+               if(e.control)return;
+               if(!contextmenu)return;
+               var c=contextmenu,m=e.page;
+               var l=c.offsetLeft,t=c.offsetTop;
+               if(m.x<l||m.x>l+c.offsetWidth||m.y<t||m.y>t+c.offsetHeight)kfm_closeContextMenu();
+       });
+       kfm_addContextMenu(document,function(e){
+               if(window.webkit||!e.control)e.stop();
+       });
+}
+function kfm_createContextMenu(m,links){
+       var row;
+       if(!window.contextmenu_loading)kfm_closeContextMenu();
+       if(!contextmenu){
+               window.contextmenu=new Element('table',{
+                       'class':'contextmenu',
+                       'styles':{
+                               'left':m.x,
+                               'top':m.y
+                       }
+               });
+               window.contextmenu.addLink=function(href,text,icon,disabled,isSubMenu, obj){
+                       if(disabled && !kfm_vars.show_disabled_contextmenu_links)return;
+                       row=kfm.addRow(this);
+                       if(disabled){
+                               row.className+=' disabled';
+                               href='';
+                       }
+                       if(isSubMenu){
+                               link=newLink('javascript:kfm_cm_openSubMenu("'+href+'",this);',text);
+                               row.className+=' is_submenu';
+                       }
+                       else if(href=='kfm_0')link=text;
+                       else{
+                               if(typeof(href)=="object"){
+                                       var display=1; // default, display
+                                       if(href.displayCheck) display=href.displayCheck(href.doParameter);
+                                       if(!display)return;
+                                       if(display==2)row.className+=' disabled';
+                                       if(!href.name && href.title)href.name=href.title; // make name title if not exists
+                                       if(!href.name) href.name='default'; // make name default if not exists
+                                       link=newLink('#',href.title);
+                                       link.doFunction=href.doFunction;
+                                       link.doParameter=href.doParameter;
+                                       link.addEvent("click",function(){
+                                               kfm_closeContextMenu();
+                                               href.doFunction(href.doParameter);
+                                       });
+                               }
+                               else link=newLink('javascript:kfm_closeContextMenu();'+href,text);
+                       }
+                       if(typeof(href)=="object") kfm.addCell(row,0,0,'','kfm_contextmenu_iconCell kfm_plugin_'+href.name+'_contexticon kfm_plugin_'+href.name+'_'+kfm_theme+'_contexticon');
+                       else kfm.addCell(row,0,0,(icon?new Element('img',{src:'themes/'+kfm_theme+'/icons/'+icon+'.png'}):''),'kfm_contextmenu_iconCell');
+                       kfm.addCell(row,1,0,link,'kfm_contextmenu_nameCell');
+                       try{
+                               row.className+=' cm_'+href.name.replace(/[^a-zA-Z]*/g,'');
+                       }catch(e){
+                               row.className+=' cm_'+link.innerHTML.replace(/[^a-zA-Z]*/g,'');
+                       }
+               };
+               window.contextmenu_loading=setTimeout('window.contextmenu_loading=null',1);
+               document.body.appendChild(contextmenu);
+       }
+       else{
+               row=kfm.addRow(contextmenu);
+               row.className+=' cm__separator';
+               var col=kfm.addCell(row,0,2);
+               col.appendChild(new Element('hr'));
+       }
+       var rows=contextmenu.rows.length;
+       for(var i=0;i<links.length;++i){
+               var link=links[i];
+               if($type(link)=="object")contextmenu.addLink(link);
+               else if(link[1])contextmenu.addLink(link[0],link[1],link[2],link[3],link[4]);
+       }
+       var w=contextmenu.offsetWidth,h=contextmenu.offsetHeight,ws=window.getSize().size;
+       if(h+m.y>ws.y)contextmenu.style.top=(ws.y-h)+'px';
+       if(w+m.x>ws.x)contextmenu.style.left=(m.x-w)+'px';
+}
+function kfm_addContextMenu(el,fn){
+       el.addEvent(window.webkit&&!window.webkit420?'mousedown':'contextmenu',function(e){
+               e=new Event(e);
+               if(e.type=='contextmenu' || e.rightClick)fn(e);
+       });
+       return el;
+}
+kfm.cm={
+       submenus:[]
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/directories.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/directories.js
new file mode 100644 (file)
index 0000000..0bc5776
--- /dev/null
@@ -0,0 +1,227 @@
+// see license.txt for licensing
+function kfm_changeDirectory(id, nofiles){
+       if(!isNaN(id))id='kfm_directory_icon_'+id;
+       if(id=='kfm_directory_icon_0')id='kfm_directory_icon_1';
+       var el=$(id),a,els=$$('td.kfm_directory_open');
+       if(!el)return;
+       setTimeout('$clear(window.dragTrigger);',1);
+       if(window.ie)while(el&&!el.node_id)el=el.parentNode;
+       kfm_cwd_name=el.kfm_directoryname;
+       kfm_cwd_id=el.node_id;
+       for(var a=0;a<els.length;++a)els[a].removeClass('kfm_directory_open');
+       el.parentNode.className+=' kfm_directory_open';
+               kfm_filesLoader();
+       if(!nofiles){
+               setTimeout('x_kfm_loadFiles(kfm_cwd_id,kfm_refreshFiles);',20);
+       }
+       setTimeout('x_kfm_loadDirectories(kfm_cwd_id,kfm_refreshDirectories);',20);
+}
+function kfm_createDirectory(id){
+       if(!kfm_vars.permissions.dir.mk)return kfm.alert('permission denied: cannot create directory');
+       kfm_prompt(kfm.lang.CreateDirMessage(kfm_directories[id].path),kfm.lang.NewDirectory,function(newName){
+               if(newName&&newName!=''&&!/\/|^\./.test(newName))x_kfm_createDirectory(id,newName,kfm_refreshDirectories);
+       });
+}
+function kfm_deleteDirectory(id){
+       if(!kfm_vars.permissions.dir.rm)return kfm.alert('permission denied: cannot delete directory');
+       if(!kfm.confirm(kfm.lang.DelDirMessage(kfm_directories[id].path)))return;
+       if(kfm_directories[id].hasChildren && !kfm.confirm(kfm.lang.RecursiveDeleteWarning(kfm_directories[id].name)))return;
+       x_kfm_deleteDirectory(id,kfm_deleteDirectoryCheck);
+}
+function kfm_deleteDirectoryCheck(res){
+       if(res.type&&res.type=='error'){
+               switch(parseInt(res.msg)){
+                       case 1: kfm_log('error: '+kfm.lang.IllegalDirectoryName(res.name)); break;
+                       case 2:{ // not empty
+                               var ok=kfm.confirm(kfm.lang.RecursiveDeleteWarning(res.name));
+                               if(ok)x_kfm_deleteDirectory(res.id,1,kfm_deleteDirectoryCheck);
+                               break;
+                       }
+                       case 3: kfm_log('error: '+kfm.lang.RmdirFailed(res.name)); break;
+                       case 4: kfm_log('error: '+kfm.lang.DirectoryNotInDb); break;
+                       default: new Notice(res.msg);
+               }
+       }
+       else{
+               var is_found=0,p=res.oldpid;
+               while(p&&!is_found){
+                       if(p==kfm_cwd_id)is_found=1;
+                       p=kfm_directories[p].parent;
+               }
+               if(is_found)kfm_changeDirectory('kfm_directory_icon_'+p);
+               kfm_refreshDirectories(res);
+       }
+}
+function kfm_dir_addLink(t,name,parent_addr,is_last,has_node_control,parent){
+       var r=kfm.addRow(t),c,pdir=parent_addr+name,name=(name==''?kfm_vars.root_folder_name:name);
+       var name_text=(new Element('span',{
+               'id':'directory_name_'+parent
+       })).setHTML('0');
+       var el=new Element('div',{
+               'id':'kfm_directory_icon_'+parent,
+               'class':'kfm_directory_link '+(kfm_cwd_name==pdir?'':'kfm_directory_open')
+       });
+       el.appendChild(name_text),
+       $extend(el,{
+               'kfm_directoryname':pdir,
+               'node_id':parent
+       }).setStyle('cursor',(window.ie?'hand':'pointer'));
+       kfm_addContextMenu(el,function(e){
+               var el=e.target;
+               while(el&&!el.node_id)el=el.parentNode;
+               if(!el)return;
+               var links=[],i,node_id=el.node_id;
+               links.push(['kfm_renameDirectory("'+node_id+'")',kfm.lang.RenameDir,'',!kfm_vars.permissions.dir.ed]);
+               links.push(['kfm_createDirectory("'+node_id+'")',kfm.lang.CreateSubDir,'folder_new',!kfm_vars.permissions.dir.mk]);
+               if(node_id!=1)links.push(['kfm_deleteDirectory("'+node_id+'")',kfm.lang.DeleteDir,'remove',!kfm_vars.permissions.dir.rm]);
+               if(kfm_return_directory)links.push(['setTimeout("window.close()",1);window.opener.SetUrl("'+kfm_directories[node_id].realpath+'/");',kfm.lang.SendToCms]);
+               e=new Event(e);
+               kfm_createContextMenu(e.page,links);
+       });
+       var cell=kfm.addCell(r,0,0,(
+               has_node_control?
+                       newLink('javascript:kfm_dir_openNode('+parent+')','[+]','kfm_dir_node_'+parent,'kfm_dir_node_closed'):
+                       (new Element('span',{'id':'kfm_dir_node_'+parent})).setHTML('&nbsp;')
+               ),'kfm_dir_lines_'+(is_last?'lastchild':'child'));
+       cell.style.width='16px';
+       cell=kfm.addCell(r,1,0,el,'kfm_dir_name');
+       if(window.webkit){ // fix cell width for konqueror
+               cell.style.width=(t.offsetWidth-16)+'px';
+       }
+       el.addEvent('click',function(e){
+               e=new Event(e);
+               if(e.rightClick)return;
+               kfm_changeDirectory(this.id);
+       });
+       el.addEvent('mouseout',function(){
+               kfm_directory_over=0;
+               this.removeClass('hovered');
+       });
+       el.addEvent('mouseover',function(){
+               if(!kfm_directory_over)kfm_directory_over=parseInt(this.node_id);
+       });
+       { // fix name width
+               var reqHeight=name_text.offsetHeight;
+               name_text.innerHTML='. '+name;
+               el=name_text;
+               el.setStyle('display','block');
+               if(reqHeight&&el.offsetHeight>reqHeight){
+                       el.title=name;
+                       kfm_shrinkName(name,el,el,'offsetHeight',reqHeight,'');
+               }
+               else el.innerHTML=name;
+               if(!window.ie)el.style.position='inherit';
+       }
+       { // subdir holder
+               r=kfm.addRow(t);
+               kfm.addCell(r,0,0,' ',is_last?0:'kfm_dir_lines_nochild');
+               kfm.addCell(r,1).id='kfm_directories_subdirs_'+parent;
+       }
+       kdnd_makeDraggable('kfm_dir_name');
+       kdnd_addDropHandler('kfm_dir_name','.kfm_dir_name',kfm_dir_dropHandler);
+       return t;
+}
+function kfm_dir_dropHandler(e){
+       var dir_from=parseInt($E('.kfm_directory_link',e.sourceElement).node_id);
+       if(dir_from==1)return;
+       var dir_to=parseInt($E('.kfm_directory_link',e.targetElement).node_id);
+       if(dir_to==0||dir_to==dir_from)return;
+       if(!kfm_vars.permissions.dir.mv)return kfm.alert(kfm.lang.CannotMoveDirectory);
+       x_kfm_moveDirectory(dir_from,dir_to,kfm_refreshDirectories);
+       kfm_selectNone();
+}
+function kfm_dir_openNode(dir){
+       var node=$('kfm_dir_node_'+dir);
+       node.className='kfm_dir_node_opened';
+       if(node.href)node.href=node.href.replace(/open/,'close');
+       $('kfm_directories_subdirs_'+dir).empty().appendText(kfm.lang.Loading);
+       x_kfm_loadDirectories(dir,kfm_refreshDirectories);
+}
+function kfm_dir_closeNode(dir){
+       var node=$('kfm_dir_node_'+dir);
+       node.className='kfm_dir_node_closed';
+       if(node.href)node.href=node.href.replace(/close/,'open');
+       $('kfm_directories_subdirs_'+dir).empty();
+}
+function kfm_refreshDirectories(res){
+       var d,p,t;
+       if(res.toString()===res)return kfm_log(res);
+       d=res.parent;
+       if(d==kfm_vars.root_folder_id){ // root node
+               p=$('kfm_directories');
+               t=new Element('table',{
+                       'id':'kfm_directories'
+               });
+               p.parentNode.replaceChild(kfm_dir_addLink(t,'','',1,0,kfm_vars.root_folder_id),p);
+               kfm_directories[kfm_vars.root_folder_id]={
+                       'parent':0,
+                       'name':kfm_vars.root_folder_name,
+                       'path':'/',
+                       'realpath':res.properties.path,
+                       'hasChildren':res.directories.length
+               }
+               $('kfm_directory_icon_'+kfm_vars.root_folder_id).parentNode.className+=' kfm_directory_open';
+       }
+       t=new Element('table'),n='kfm_dir_node_'+d;
+       t.setStyle('table-layout','fixed');
+       dirwrapper=$('kfm_directories_subdirs_'+d).empty();
+       dirwrapper.appendChild(t);
+       var dirs=$A(res.directories);
+       dirs.each(function(dir,a){
+               kfm_dir_addLink(t,dir[0],res.reqdir,l=(a==dirs.length-1),dir[1],dir[2]);
+               if(!kfm_directories[dir[2]])kfm_directories[dir[2]]={
+                       'parent':res.parent,
+                       'name':dir[0],
+                       'path':res.reqdir+dir[0],
+                       'realpath':res.properties.path+dir[0]+'/',
+                       'hasChildren':dir[1]
+               };
+       });
+       if(d!='')$($(n).parentNode).empty().appendChild(dirs.length?
+               newLink('javascript:kfm_dir_closeNode("'+res.parent+'")','[-]',n,'kfm_dir_node_open'):
+               (new Element('span',{
+                       'id':n
+               })).setHTML(' ')
+       );
+       kfm_cwd_subdirs[d]=res.directories;
+       if(!kfm_cwd_subdirs[d])kfm_dir_openNode(res.parent);
+       kfm_setDirectoryProperties(res.properties);
+       if(!kfm_vars.startup_sequence)kfm_selectNone();
+       kfm_log(kfm.lang.DirRefreshed);
+       kfm_directories[kfm_cwd_id]=res.properties;
+       kfm_directories[d].hasChildren=1;
+       if(kfm_startup_sequence_index<kfm_vars.startup_sequence.length){
+               kfm_changeDirectory(kfm_vars.startup_sequence[kfm_startup_sequence_index],true);
+               kfm_startup_sequence_index++;
+               if(kfm_startup_sequence_index > kfm_vars.startup_sequence.length)kfm_vars.startup_sequence=false;
+       }
+       else kfm_refreshPanels('kfm_left_column');
+}
+function kfm_renameDirectory(id){
+       var directoryName=kfm_directories[id].name;
+       kfm_prompt(kfm.lang.RenameTheDirectoryToWhat(directoryName),directoryName,function(newName){
+               if(!newName||newName==directoryName)return;
+               kfm_directories[id]=null;
+               kfm_log(kfm.lang.RenamedDirectoryAs(directoryName,newName));
+               x_kfm_renameDirectory(id,newName,kfm_refreshDirectories);
+       });
+}
+function kfm_setDirectoryProperties(properties){
+       if(!$('kfm_directory_properties'))return;
+       var wrapper=$('kfm_directory_properties').empty();
+       wrapper.properties=properties;
+       var table=new Element('table'),row,cell,i;
+       { // directory name
+               i=properties.allowed_file_extensions.length?properties.allowed_file_extensions.join(', '):kfm.lang.NoRestrictions;
+               row=kfm.addRow(table);
+               kfm.addCell(row,0,0,(new Element('strong')).setHTML(kfm.lang.Name));
+               kfm.addCell(row,1,0,'/'+kfm_cwd_name);
+       }
+       { // allowed file extensions
+               i=properties.allowed_file_extensions.length?properties.allowed_file_extensions.join(', '):kfm.lang.NoRestrictions;
+               row=kfm.addRow(table);
+               kfm.addCell(row,0,0,(new Element('strong')).setHTML(kfm.lang.AllowedFileExtensions));
+               kfm.addCell(row,1,0,i);
+       }
+       wrapper.appendChild(table);
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/file.class.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/file.class.js
new file mode 100644 (file)
index 0000000..f34f064
--- /dev/null
@@ -0,0 +1,82 @@
+var File=new Class({
+       getText:function(varname){
+               var el=new Element('span',{
+                       'class':varname+' file_'+varname+'_'+this.id
+               });
+               this.setText(el,varname);
+               if(!this.textInstances[varname])this.textInstances[varname]=[];
+               this.textInstances[varname].push(el);
+               return el;
+       },
+       initialize:function(id,data){
+               this.id=id;
+               this.textInstances=[];
+               if(data){
+                       File_Instances[id]=this;
+                       File_setData(data,this);
+               }
+               else x_kfm_getFileDetails(id,File_setData);
+       },
+       setText:function(el,varname){
+               el.empty();
+               var v=$pick(this[varname],'');
+               if(varname=='name'){
+                       if(!kfm_listview && kfm_vars.files.name_length_displayed && kfm_vars.files.name_length_displayed<v.length){
+                               el.title=v;
+                               v=v.substring(0,kfm_vars.files.name_length_displayed-3)+'...';
+                       }
+                       else if(kfm_listview && kfm_vars.files.name_length_in_list && kfm_vars.files.name_length_in_list<v.length){
+                               el.title=v;
+                               v=v.substring(0,kfm_vars.files.name_length_in_list-3)+'...';
+                       }
+               }
+               if(varname=='modified' && !v){
+                       var v=(new Date(this.ctime*1000)).toGMTString().replace(/ GMT$/,'');
+                       this.modified=v;
+               }
+               el.appendText(v);
+       },
+       setThumbnailBackground:function(el,reset){
+               if(this.icon_loaded && !reset)el.setStyle('background-image','url("'+this.icon_url+'")');
+               else{
+                       var url='get.php?id='+this.id+'&width=64&height=64&get_params='+kfm_vars.get_params+'&r'+Math.random();
+                       var img=new Element('img',{
+                               src:url,
+                               styles:{
+                                       width:1,
+                                       height:1
+                               }
+                       });
+                       var id=this.id;
+                       img.addEvent('load',function(){
+                               var p=this.parentNode;
+                               p.setStyle('background-image','url("'+url+'")');
+                               var F=File_getInstance(id);
+                               F.icon_loaded=1;
+                               F.icon_url=url;
+                               this.remove();
+                       });
+                       kfm.addEl(el,img);
+               }
+       }
+});
+function File_getInstance(id,data){
+       id=parseInt(id);
+       if(isNaN(id))return;
+       if(!File_Instances[id] || data)File_Instances[id]=new File(id,data);
+       return File_Instances[id];
+}
+function File_setData(el,F){
+       var id=+el.id;
+       el=$H(el);
+       if(!F)F=File_getInstance(id);
+       el.each(function(varvalue,varname){
+               F[varname]=varvalue;
+               if(!F.textInstances || !F.textInstances[varname])return;
+               F.textInstances[varname].each(function(t){
+                       F.setText(t,varname);
+               });
+       });
+       File_Instances[id]=F;
+}
+var File_Instances=[];
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/file.selections.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/file.selections.js
new file mode 100644 (file)
index 0000000..b9722c7
--- /dev/null
@@ -0,0 +1,225 @@
+// see ../license.txt for licensing
+function kfm_addToSelection(id){
+       id=parseInt(id);
+       if(!id || selectedFiles.contains(id))return;
+       selectedFiles.push(id);
+       $('kfm_file_icon_'+id).className+=' selected';
+       if(kfm_log_level>0)kfm_log(kfm.lang.FileSelected(id));
+       kfm_selectionCheck();
+}
+function kfm_chooseFile(){
+       if(selectedFiles.length>1 && !kfm_vars.files.allow_multiple_returns)return kfm.alert(kfm.lang.NotMoreThanOneFile);
+       if(kfm_vars.files.return_id_to_cms){
+               window.opener.SetUrl(selectedFiles.join(','));
+               setTimeout('window.close()',1);
+       }
+       else {
+               x_kfm_getFileUrls(selectedFiles,function(urls){
+                       if(copy_to_clipboard)copy_to_clipboard(urls.join("\n"));
+                       if(!window.opener || kfm_file_handler=='download'){
+                               var allImages=1;
+                               for(var i=0;i<selectedFiles.length;++i)if(!File_getInstance(selectedFiles[i]).width)allImages=0;
+                               if(!allImages){
+                                       for(var i=0;i<urls.length;++i){
+                                               var url=urls[i];
+                                               if(/get.php/.test(url))url+='&forcedownload=1';
+                                               document.location=url;
+                                       }
+                               }
+                               else kfm_img_startLightbox(selectedFiles)
+                               return;
+                       }
+                       if(selectedFiles.length==1&&File_getInstance(selectedFiles[0]).width)window.opener.SetUrl(urls[0].replace(/([^:]\/)\//g,'$1'),0,0,File_getInstance(selectedFiles[0]).caption);
+                       else{
+                               if(selectedFiles.length==1)window.opener.SetUrl(urls[0]);
+                               else window.opener.SetUrl('"'+urls.join('","')+'"');
+                       }
+                       setTimeout('window.close()',1);
+               });
+       }
+}
+function kfm_isFileSelected(filename){
+       return kfm_inArray(filename,selectedFiles);
+}
+function kfm_removeFromSelection(id){
+       if(!id)return;
+       var i;
+       for(i=0;i<selectedFiles.length;++i){
+               if(selectedFiles[i]==id){
+                       var el=$('kfm_file_icon_'+id);
+                       if(el)el.removeClass('selected');
+                       kfm_selectionCheck();
+                       return selectedFiles.splice(i,1);
+               }
+       }
+}
+function kfm_selectAll(){
+       kfm_selectNone();
+       var a,b=$('documents_body').fileids;
+       for(a=0;a<b.length;++a)kfm_addToSelection(b[a]);
+}
+function kfm_selectInvert(){
+       var a,b=$('documents_body').fileids;
+       for(a=0;a<b.length;++a)if(kfm_isFileSelected(b[a]))kfm_removeFromSelection(b[a]);
+       else kfm_addToSelection(b[a]);
+}
+function kfm_selectNone(){
+       if(kfm_lastClicked){
+               var el=$('kfm_file_icon_'+kfm_lastClicked);
+               if(el)el.removeClass('last_clicked');
+       }
+       for(var i=selectedFiles.length;i>-1;--i)kfm_removeFromSelection(selectedFiles[i]);
+       kfm_lastClicked=0;
+       kfm_selectionCheck();
+}
+function kfm_selectionCheck(){
+       if(selectedFiles.length==1){
+               var el=$E('#kfm_file_details_panel div.kfm_panel_body');
+               if(el)el.innerHTML='loading';
+               kfm_run_delayed('file_details','if(selectedFiles.length==1)kfm_showFileDetails(selectedFiles[0]);');
+       }
+       else kfm_run_delayed('file_details','if(!selectedFiles.length)kfm_showFileDetails();');
+}
+function kfm_selection_drag(e){
+       e=new Event(e);
+       if(!window.dragType||window.dragType!=2||!window.drag_wrapper)return;
+       clearSelections();
+       var p1=e.page,p2=window.drag_wrapper.orig;
+       var x1=p1.x>p2.x?p2.x:p1.x;
+       var x2=p2.x>p1.x?p2.x:p1.x;
+       var y1=p1.y>p2.y?p2.y:p1.y;
+       var y2=p2.y>p1.y?p2.y:p1.y;
+       window.drag_wrapper.setStyles('display:block;left:'+x1+'px;top:'+y1+'px;width:'+(x2-x1)+'px;height:'+(y2-y1)+'px;zIndex:4');
+}
+function kfm_selection_dragFinish(e){
+       e=new Event(e);
+       $clear(window.dragSelectionTrigger);
+       if(!window.drag_wrapper)return;
+       var right_column=$('documents_body'),p1=e.page,p2=window.drag_wrapper.orig,offset=right_column.scrollTop;
+       var x1=p1.x>p2.x?p2.x:p1.x, x2=p2.x>p1.x?p2.x:p1.x, y1=p1.y>p2.y?p2.y:p1.y, y2=p2.y>p1.y?p2.y:p1.y;
+//     y1+=offset;
+//     y2+=offset;
+       setTimeout('window.dragType=0;',1); // pause needed for IE
+       window.drag_wrapper.remove();
+       window.drag_wrapper=null;
+       document.removeEvent('mousemove',kfm_selection_drag);
+       document.removeEvent('mouseup',kfm_selection_dragFinish);
+       var fileids=right_column.fileids;
+       for(var i=0;i<fileids.length;++i){
+               var curIcon=$('kfm_file_icon_'+fileids[i]);
+               var curTop=getOffset(curIcon,'Top');
+               var curLeft=getOffset(curIcon,'Left');
+               if((curLeft+curIcon.offsetWidth)>x1&&curLeft<x2&&(curTop+curIcon.offsetHeight)>y1&&curTop<y2)kfm_addToSelection(fileids[i]);
+       }
+       kfm_selectionCheck();
+}
+function kfm_selection_dragStart(e){
+       if(window.dragType)return;
+       if (!kfm_vars.use_templates && window.mouseAt.x > $('kfm_right_column').scrollWidth + $('kfm_left_column').scrollWidth - 15) return;
+       window.dragType=2;
+       var w=window.getSize().size;
+       document.addEvent('mouseup',kfm_selection_dragFinish);
+       window.drag_wrapper=new Element('div',{
+               'id':'kfm_selection_drag_wrapper',
+               'styles':{
+                       'display':'none'
+               }
+       });
+       window.drag_wrapper.orig=window.mouseAt;
+       kfm.addEl(document.body,window.drag_wrapper);
+       document.addEvent('mousemove',kfm_selection_drag);
+}
+function kfm_shiftFileSelectionLR(dir){
+       if(selectedFiles.length>1)return;
+       var na=$('documents_body').fileids,a=0,ns=na.length;
+       if(selectedFiles.length){
+               for(;a<ns;++a)if(na[a]==selectedFiles[0])break;
+               if(dir>0){if(a==ns-1)a=-1}
+               else if(!a)a=ns;
+       }
+       else a=dir>0?-1:ns;
+       kfm_selectSingleFile(na[a+dir]);
+}
+function kfm_shiftFileSelectionUD(dir){
+       if(selectedFiles.length>1)return;
+       var na=$('documents_body').fileids,a=0,ns=na.length,icons_per_line=0,topOffset=$('kfm_file_icon_'+na[0]).offsetTop;
+       if(selectedFiles.length){
+               if(topOffset==$('kfm_file_icon_'+na[ns-1]).offsetTop)return; // only one line of icons
+               for(;$('kfm_file_icon_'+na[icons_per_line]).offsetTop==topOffset;++icons_per_line);
+               for(;a<ns;++a)if(na[a]==selectedFiles[0])break; // what is the selected file
+               a+=icons_per_line*dir;
+               if(a>=ns)a=ns-1;
+               if(a<0)a=0;
+       }
+       else a=dir>0?0:ns-1;
+       kfm_selectSingleFile(na[a]);
+}
+function kfm_toggleSelectedFile(e){
+       var row;
+       e=new Event(e);
+       if(e.rightClick)return;
+       e.stopPropagation();
+       if(window.dragAddedFileToSelection){
+               window.dragAddedFileToSelection=false;
+               return;
+       }
+       var el=e.target;
+       while(el.tagName!='DIV')el=el.parentNode;
+       var id=el.file_id;
+       if(kfm_listview){
+               row=el;
+               while(row.nodeName!='TR')row=row.parentNode;
+               rowInd=row.rowIndex;
+       }
+       if(kfm_lastClicked){
+               var el=$('kfm_file_icon_'+kfm_lastClicked);
+               if(el)el.removeClass('last_clicked');
+               else kfm_lastClicked=0;
+       }
+       if(kfm_lastClicked&&e.shift){
+               var e=kfm_lastClicked;
+               if(kfm_listview){
+                       row=el;
+                       while(row.nodeName!='TR')row=row.parentNode;
+                       smalRow=Math.min(row.rowIndex,rowInd);
+                       bigRow=Math.max(row.rowIndex,rowInd);
+                       $j('#kfm_files_listview_table tbody tr:lt('+bigRow+')').each(function(){
+                               if(this.rowIndex>=smalRow)kfm_addToSelection(this.fileid);
+                       });
+               }else{
+                       clearSelections(e);
+                       kfm_selectNone();
+                       var a=$('documents_body').fileids,b,c,d;
+                       for(b=0;b<a.length;++b){
+                               if(a[b]==e)c=b;
+                               if(a[b]==id)d=parseInt(b);
+                       }
+                       if(c>d){
+                               b=c;
+                               c=d;
+                               d=b;
+                       }
+                       for(;c<=d;++c)kfm_addToSelection(a[c]);
+               }
+       }
+       else{
+               if(kfm_isFileSelected(id)){
+                       if(!e.control)kfm_selectNone();
+                       else kfm_removeFromSelection(id);
+               }
+               else{
+                       if(!e.control&&!e.meta)kfm_selectNone();
+                       kfm_addToSelection(id);
+               }
+       }
+       kfm_lastClicked=id;
+       $('kfm_file_icon_'+id).className+=' last_clicked';
+}
+function kfm_selectSingleFile(id){
+       kfm_selectNone();
+       kfm_addToSelection(id);
+       var panel=$('kfm_right_column'),el=$('kfm_file_icon_'+id);
+       var offset=panel.scrollTop,panelHeight=panel.offsetHeight,elTop=getOffset(el,'Top'),elHeight=el.offsetHeight;
+       if(elTop+elHeight-offset>panelHeight)panel.scrollTop=elTop-panelHeight+elHeight;
+       else if(elTop<offset)panel.scrollTop=elTop;
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/file.text-editing.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/file.text-editing.js
new file mode 100644 (file)
index 0000000..113a6f2
--- /dev/null
@@ -0,0 +1,106 @@
+// see ../license.txt for licensing
+function kfm_createEmptyFile(filename,msg){
+       if(!filename || filename.toString()!==filename){
+               filename='';
+               msg='';
+       }
+       var not_ok=0;
+       kfm_prompt(kfm.lang.WhatFilenameToCreateAs+msg,filename,function(filename){
+               if(!filename)return;
+               if(kfm_isFileInCWD(filename)){
+                       var o=kfm.confirm(kfm.lang.AskIfOverwrite(filename));
+                       if(!o)not_ok=1;
+               }
+               if(filename.indexOf('/')>-1){
+                       msg=kfm.lang.NoForwardslash;
+                       not_ok=1;
+               }
+               if(not_ok)return kfm_createEmptyFile(filename,msg);
+               x_kfm_createEmptyFile(kfm_cwd_id,filename,kfm_refreshFiles);
+       });
+}
+function kfm_leftColumn_disable(){
+       var left_column=$('kfm_left_column');
+       document.body.appendChild(new Element('div',{
+               'id':'kfm_left_column_hider',
+               'styles':{
+                       'position':'absolute',
+                       'left':0,
+                       'top':0,
+                       'width':left_column.offsetWidth,
+                       'height':left_column.offsetHeight,
+                       'opacity':'.7',
+                       'background':'#fff'
+               }
+       }));
+       kfm_resizeHandler_addMaxHeight('kfm_left_column_hider');
+}
+function kfm_leftColumn_enable(){
+       if(!$("kfm_left_column_hider"))return;
+       $("kfm_left_column_hider").remove();
+       kfm_resizeHandler_removeMaxHeight('kfm_left_column_hider');
+}
+function kfm_textfile_attachKeyBinding(){
+       if(!codepress.editor||!codepress.editor.body)return setTimeout('kfm_textfile_attachKeyBinding();',1);
+       var doc=codepress.contentWindow.document;
+       if(doc.attachEvent)doc.attachEvent('onkeypress',kfm_textfile_keybinding);
+       else doc.addEventListener('keypress',kfm_textfile_keybinding,false);
+}
+function kfm_textfile_close(){
+       if($("edit-start").value!=codepress.getCode() && !kfm.confirm( kfm.lang.CloseWithoutSavingQuestion))return;
+       kfm_leftColumn_enable();
+       kfm_changeDirectory("kfm_directory_icon_"+kfm_cwd_id);
+       $('kfm_right_column').removeEvent('keyup',kfm_textfile_keybinding);
+}
+function kfm_textfile_createEditor(){
+       CodePress.run();
+       if($("kfm_tooltip"))$("kfm_tooltip").remove();
+       kfm_textfile_attachKeyBinding();
+}
+function kfm_textfile_initEditor(res,readonly){
+       if(!$('kfm_left_column_hider'))kfm_leftColumn_disable();
+       var t=new Element('table',{
+               'id':'kfm_editFileTable',
+               'styles':{
+                       'width':'100%'
+               }
+       });
+       var right_column=$('kfm_right_column').empty();
+       right_column.addEvent('keyup',kfm_textfile_keybinding);
+       right_column.contentMode='codepress';
+       right_column.appendChild(t);
+       var r2=kfm.addRow(t),c=0;
+       kfm.addCell(r2,c++,1,res.name);
+       if(!readonly){ /* show option to save edits */
+               kfm.addCell(r2,c++,1,newLink('javascript:new Notice("saving file...");$("edit-start").value=codepress.getCode();x_kfm_saveTextFile('+res.id+',$("edit-start").value,kfm_showMessage);','Save',0,'button'));
+       }
+       kfm.addCell(r2,c++,1,newLink('javascript:kfm_textfile_close()',kfm.lang.Close,0,'button'));
+       var row=$(kfm.addRow(t));
+       r3=kfm.addCell(row,0,c);
+       r3.id='kfm_codepressTableCell';
+       var className='codepress '+res.language+(readonly?' readonly-on':'');
+       var h=window.getSize().size.y-t.offsetHeight-2;
+       if(window.ie)h-=13;
+       var codeEl=new Element('textarea',{
+               'id':'codepress',
+               'class':className,
+               'value':res.content,
+               'title':res.name,
+               'styles':{
+                       'width':t.offsetWidth-25,
+                       'height':h
+               }
+       });
+       changeCheckEl=newInput('edit-start','textarea',res.content);
+       changeCheckEl.setStyle('display','none');
+       r3.appendChild(codeEl);
+       r3.appendChild(changeCheckEl);
+       if(window.CodePress)kfm_textfile_createEditor();
+       else loadJS('j/codepress-0.9.6/codepress.js','cp-script','en-us','kfm_textfile_createEditor();');
+}
+function kfm_textfile_keybinding(e){
+       e=new Event(e);
+       if(e.code!=27)return;
+       e.stopPropagation();
+       kfm_textfile_close();
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/files.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/files.js
new file mode 100644 (file)
index 0000000..e1bc8d8
--- /dev/null
@@ -0,0 +1,458 @@
+// see license.txt for licensing
+var kfm_file_bits={
+       dragDisplay:function(){
+               window.dragAddedFileToSelection=false;
+               if(!kfm_isFileSelected(this.file_id)){
+                       kfm_addToSelection(this.file_id);
+                       window.dragAddedFileToSelection=true;
+               }
+               var drag_wrapper=new Element('div',{
+                       'id':'kfm_drag_wrapper',
+                       styles:{
+                               'min-width':100,
+                               'opacity':'.7'
+                       }
+               });
+               for(var i=0;i<10&&i<selectedFiles.length;++i)kfm.addEl(drag_wrapper,[File_getInstance(selectedFiles[i]).name,new Element('br')]);
+               if(selectedFiles.length>10)kfm.addEl(
+                       drag_wrapper,
+                       (new Element('i')).setHTML(kfm.lang.AndNMore(selectedFiles.length-10))
+               );
+               return drag_wrapper;
+       },
+       padding:0
+}
+function kfm_buildFileDetailsTable(res){
+       if(!res)return kfm_log('error: missing file details?');
+       var table=new Element('table'),r;
+       if(res.name){ // filename
+               r=kfm.addRow(table);
+               kfm.addCell(r,0,0,(new Element('strong')).setHTML(kfm.lang.Filename));
+               kfm.addCell(r,1,0,res.name);
+       }
+       if(res.filesize){ // filesize
+               r=kfm.addRow(table);
+               kfm.addCell(r,0,0,(new Element('strong')).setHTML(kfm.lang.Filesize));
+               kfm.addCell(r,1,0,res.filesize);
+       }
+       if(res.tags&&res.tags.length){ // tags
+               r=kfm.addRow(table);
+               kfm.addEl(kfm.addCell(r,0),(new Element('strong')).setHTML(kfm.lang.Tags));
+               var arr=[],c=kfm.addCell(r,1);
+               for(var i=0;i<res.tags.length;++i){
+                       kfm.addEl(c,kfm_tagDraw(res.tags[i]));
+                       if(i!=res.tags.length-1)kfm.addEl(c,', ');
+               }
+       }
+       if(res.mimetype){ // mimetype
+               r=kfm.addRow(table);
+               kfm.addEl(kfm.addCell(r,0),(new Element('strong')).setHTML(kfm.lang.Mimetype));
+               kfm.addEl(kfm.addCell(r,1),res.mimetype);
+               switch(res.mimetype.replace(/\/.*/,'')){
+                       case 'image':{
+                               if(res.caption){ // caption
+                                       r=kfm.addRow(table);
+                                       kfm.addCell(r,0,0,(new Element('strong')).setHTML(kfm.lang.Caption));
+                                       kfm.addCell(r,1).innerHTML=(res.caption).replace(/\n/g,'<br \/>');
+                               }
+                               break;
+                       }
+               }
+       }
+       if(res.ctime){ // last change time
+               r=kfm.addRow(table);
+               kfm.addEl(kfm.addCell(r,0),(new Element('strong')).setHTML(kfm.lang.LastModified));
+               var d=(new Date(res.ctime*1000)).toGMTString();
+               kfm.addEl(kfm.addCell(r,1),d);
+       }
+       if(res.width) {
+               r=kfm.addRow(table);
+               kfm.addCell(r,0,0,(new Element('strong')).setHTML(kfm.lang.ImageDimensions));
+               kfm.addCell(r,1,0,res.width+" x "+res.height);    
+       }
+       return table;
+}
+function kfm_deleteFile(id){
+       if(!kfm_vars.permissions.file.rm)return kfm.alert(kfm.lang.PermissionDeniedCannotDeleteFile);
+       var filename=File_getInstance(id).name;
+       if(kfm.confirm(kfm.lang.DelFileMessage(filename))){
+               x_kfm_rm([id],kfm_removeFilesFromView);
+       }
+}
+function kfm_deleteSelectedFiles(){
+       if(!kfm_vars.permissions.file.rm)return kfm.alert('permission denied: cannot delete files');
+       kfm_deleteFiles(selectedFiles);
+}
+function kfm_deleteFiles(files){
+       var names=[],m='';
+        var dfiles=[]; // break reference system
+        for(var j=0;j<files.length;j++)dfiles.push(files[j]);//breaking reference to selectedFiles
+       if(dfiles.length>10){
+               for(var i=0;i<9;++i)names.push(File_getInstance(dfiles[i]).name);
+               m='\n'+kfm.lang.AndNMore(dfiles.length-9);
+       }
+       else for(var i=0;i<dfiles.length;++i)names.push(File_getInstance(dfiles[i]).name);
+       if(kfm.confirm(kfm.lang.DelMultipleFilesMessage+names.join('\n')+m))x_kfm_rm(dfiles,kfm_removeFilesFromView);
+}
+function kfm_downloadFileFromUrl(filename,msg){
+       if(filename.toString()!==filename)filename='';
+       var url=$('kfm_url').value;
+       if(url.substring(0,4)!='http'){
+               kfm_log(kfm.lang.UrlNotValidLog);
+               return;
+       }
+       if(!filename)filename=url.replace(kfm_regexps.all_up_to_last_slash,'');
+       var not_ok=0,o;
+       kfm_prompt(kfm.lang.FileSavedAsMessage+msg,filename,function(filename){
+               if(!filename)return;
+               if(kfm_isFileInCWD(filename)){
+                       o=kfm.confirm(kfm.lang.AskIfOverwrite(filename));
+                       if(!o)not_ok=1;
+               }
+               if(filename.indexOf('/')>-1){
+                       msg=kfm.lang.NoForwardslash;
+                       not_ok=1;
+               }
+               if(not_ok)return kfm_downloadFileFromUrl(filename,msg);
+               x_kfm_downloadFileFromUrl(url,filename,kfm_refreshFiles);
+               $('kfm_url').value='';
+       });
+}
+function kfm_downloadSelectedFiles(id){
+       var wrapper=$('kfm_download_wrapper');
+       if(!wrapper){
+               wrapper=new Element('div',{
+                       'id':'kfm_download_wrapper',
+                       'styles':{
+                               'display':'none'
+                       }
+               });
+               kfm.addEl(document.body,wrapper);
+       }
+       wrapper.empty();
+       if(id)kfm_downloadSelectedFiles_addIframe(wrapper,id);
+       else for(var i=0;i<selectedFiles.length;++i)kfm_downloadSelectedFiles_addIframe(wrapper,selectedFiles[i]);
+}
+function kfm_downloadSelectedFiles_addIframe(wrapper,id){
+       var iframe=new Element('iframe');
+       iframe.src='get.php?id='+id+'&forcedownload=1';
+       kfm.addEl(wrapper,iframe);
+}
+function kfm_extractZippedFile(id){
+       x_kfm_extractZippedFile(id,kfm_refreshFiles);
+}
+function kfm_files_reflowIcons(){
+       var panel=$('documents_body');
+       if(panel.contentMode!='file_icons')return;
+       var els=$ES('.kfm_file_icon',panel);
+       for(var i=0;i<els.length;++i){
+               var el=els[i];
+               el.setStyle('clear','none');
+               if(i&&els[i-1].offsetLeft>=el.offsetLeft)el.setStyle('clear','left');
+       }
+}
+function kfm_isFileInCWD(id){
+       var i,files=$('documents_body').fileids;
+       for(i=0;i<files.length;++i)if(files[i]==id)return true;
+       return false;
+}
+function kfm_incrementalFileDisplay(){
+       var b=window.kfm_incrementalFileDisplay_vars,fsdata=b.data.files,wrapper=$('documents_body');
+       var icon=new Element('div',{
+               'class':'kfm_file '+(kfm_listview?'kfm_file_listview':'kfm_file_icon'),
+               'styles':{
+                       'cursor':(window.ie?'hand':'pointer')
+               },
+               'events':{
+                       'click':kfm_toggleSelectedFile,
+                       'dblclick':function(e){
+                               e=new Event(e);
+                               var el=e.target;
+                               while(!el.file_id && el)el=el.parentNode;
+                               if(!el)return;
+                               var id=el.file_id;
+                               kfm_selectNone();
+                               kfm_addToSelection(id);
+                               var openingHook=kfm_getDefaultOpener(id);
+                               if(!window.opener && openingHook)openingHook.doFunction([id]);
+                               else kfm_chooseFile();
+                       }
+               }
+       });
+       if(!kfm_listview){
+               icon.addEvent('mouseover',function(e){ // initialise info tooltip
+                       if(window.kfm_tooltipInit)$clear(window.kfm_tooltipInit);
+                       if(window.kdnd_dragging)return; // don't open if currently dragging files
+                       e=new Event(e);
+                       window.kfm_tooltipInit=setTimeout('kfm_showToolTip('+e.target.file_id+')',1000);
+               });
+               icon.addEvent('mouseout',function(){ // remove info tooltip
+                       if(window.kfm_tooltipInit)$clear(window.kfm_tooltipInit);
+                       var o=$('kfm_tooltip');
+                       if(o)o.remove();
+               });
+       }
+       kfm_addContextMenu(icon,function(e){
+               var el=e.target;
+               while(el.parentNode&&!el.file_id)el=el.parentNode;
+               if(!el.parentNode)return;
+               { // variables
+                       var i,id=el.file_id;
+                       var F=File_getInstance(id);
+                       var extension=F.name.replace(/.*\./,'').toLowerCase();
+                       var writable=F.writable;
+               }
+               { // add the links
+                       var links=[],a,b,c;
+                       if(selectedFiles.length>1)links=kfm_getLinks(selectedFiles);
+                       else{
+                               a=kfm_getDefaultOpener(id);
+                               if(a){
+                                       b=$j.extend({},a);
+                                       b.name='open'; // TODO: string
+                                       b.title='open'; // TODO: string
+                                       links.push(b);
+                               }
+                               var a=kfm_getLinks([id]);
+                               for(b=0;b<a.length;++b)links.push(a[b]); 
+                       }
+                       if(selectedFiles.length<=1 && F.width)links.push(['kfm_changeCaption('+id+')',kfm.lang.ChangeCaption,'edit',!kfm_vars.permissions.file.ed]);
+                       //links.push(['kfm_tagAdd('+id+')',kfm.lang.AddTagsToFiles,'add_tags',!kfm_vars.permissions.file.ed]);
+                       //links.push(['kfm_tagRemove('+id+')',kfm.lang.RemoveTagsFromFiles,'',!kfm_vars.permissions.file.ed]);
+                       kfm_createContextMenu(e.page,links);
+               }
+       });
+       do{
+               var a,fdata,name,F,nameEl,el,fullfilename,id;
+               a=b.at;
+               fdata=fsdata[a];
+               if(wrapper.contentMode!='file_icons')return (window.kfm_incrementalFileDisplay_vars=null);
+               name=fdata.name;
+               fullfilename=kfm_cwd_name+'/'+name;
+               id=fdata.id;
+               F=File_getInstance(id,fdata);
+               ext=fdata.ext;
+               nameEl=F.getText('name');
+               el=icon.cloneNode(true);
+               el.cloneEvents(icon);
+               if(!kfm_listview)$j(el).addClass('kfm_icontype_'+ext);
+               el.id='kfm_file_icon_'+id;
+               el.dragDisplay=kfm_file_bits.dragDisplay;
+               var writable=fdata.writable;
+               { // file attributes
+                       el.file_id=id;
+                       if(!kfm_listview && fdata.width)F.setThumbnailBackground(el);
+                       wrapper.files[a]=el;
+               }
+               kfm.addEl(wrapper,el);
+               if(kfm_listview){
+                       var cs=0,cell;
+                       var listview_table=$j('#kfm_files_listview_table tbody').get(0);
+                       var rows=listview_table.rows.length;
+                       var row=listview_table.insertRow(rows);
+                       row.fileid=F.id;
+                       cell=row.insertCell(cs++);
+                       cell.className='listview_icon listview_icon_'+ext;
+                       if(window.ie)cell.innerHTML='&nbsp;';
+                       else cell.setHTML('&nbsp;');
+                       row.insertCell(cs++).appendChild(el);
+                       { // file size
+                               cell=row.insertCell(cs++);
+                               var hidden=document.createElement('span');
+                               hidden.style.display='none';
+                               hidden.appendChild(document.createTextNode(F.filesize_raw));
+                               cell.appendChild(hidden);
+                               cell.appendChild(F.getText('filesize'));
+                       }
+                       row.insertCell(cs++).appendChild(F.getText('ext'));
+                       { // modified time
+                               cell=row.insertCell(cs++);
+                               var hidden=document.createElement('span');
+                               hidden.style.display='none';
+                               hidden.appendChild(document.createTextNode(F.ctime));
+                               cell.appendChild(hidden);
+                               cell.appendChild(F.getText('modified'));
+                       }
+               }
+               else wrapper.appendChild(el);
+               el.appendChild(nameEl);
+               if(a&&$('kfm_file_icon_'+fsdata[a-1].id).offsetLeft>=el.offsetLeft)el.setStyle('clear','left');
+               window.kfm_incrementalFileDisplay_vars.at=a+1;
+       }while(a+1<fsdata.length && (a+1)%kfm_show_files_in_groups_of);
+       if(a+1<fsdata.length)window.kfm_incrementalFileDisplay_loader=setTimeout('kfm_incrementalFileDisplay()',1);
+       else{
+               kdnd_makeDraggable('kfm_file');
+               if(kfm_listview){
+                       $j('#kfm_tooltip').remove();
+                       $j('#kfm_files_listview_table').columnSizing();
+                       $j('#kfm_files_listview_table').tablesorter({
+                               sortList:[[1,0]],
+                               headers:{
+                                       1:{
+                                               sorter:'kfmobject'
+                                       }
+                               },
+                               widgets:['zebra']
+                       });
+               }
+               $j('#documents_loader').empty().html('&nbsp;');
+               if(kfm_vars.startup_selectedFiles){
+                       for(var i=0;i<kfm_vars.startup_selectedFiles.length;++i)kfm_addToSelection(kfm_vars.startup_selectedFiles[i]);
+                       kfm_vars.startup_selectedFiles=false;
+               }
+       }
+}
+function kfm_refreshFiles(res){
+       if(!res.files)return;
+       $j('#folder_info').text(res.files.length+(res.files.length==1?' file':' files')); //TODO new string
+       kdnd_addDropHandler('kfm_file','.kfm_directory_link',function(e){
+               dir_over=e.targetElement.node_id;
+               var mv='x_kfm_moveFiles(['+selectedFiles.join(',')+'],'+dir_over+',function(e){if($type(e)=="string")return alert(kfm.lang.CouldNotMoveFiles);kfm_removeFilesFromView(['+selectedFiles.join(',')+'])});kfm_selectNone()';
+               var cp='x_kfm_copyFiles(['+selectedFiles.join(',')+'],'+dir_over+',kfm_showMessage);kfm_selectNone()';
+               if(kfm_vars.files.drags_move_or_copy == 1)eval(mv); // always Move
+               else if(kfm_vars.files.drags_move_or_copy == 2)eval(cp); // always Copy
+               else{
+                       var links=[];
+                       links.push([cp,kfm.lang.CopyFiles]);
+                       links.push([mv,kfm.lang.MoveFiles,0,!kfm_vars.permissions.file.mv]);
+                       kfm_createContextMenu(e.page,links);
+               }
+       });
+       if(window.kfm_incrementalFileDisplay_loader){
+               $clear(window.kfm_incrementalFileDisplay_loader);
+               window.kfm_incrementalFileDisplay_vars=null;
+       }
+       kfm_selectNone();
+       if(!res)return;
+       if(res.parent)kfm_cwd_id=res.parent;
+       if(res.toString()===res)return kfm_log(res);
+       window.kfm_incrementalFileDisplay_vars={at:0,data:res};
+       var a,b,lowest_name,lowest_index,wrapper=$('documents_body').empty();
+       $extend(wrapper,{contentMode:'file_icons',fileids:[],files:[]});
+       $j('#cwd_display').text(kfm.lang.CurrentWorkingDir(res.reqdir));
+       { // order files by name
+               if(!res.files)res.files=[];
+               for(a=0;a<res.files.length-1;++a){
+                       lowest_name=res.files[a].name;
+                       lowest_index=a;
+                       for(b=a+1;b<res.files.length;++b){
+                               if(res.files[b].name<lowest_name){
+                                       lowest_index=b;
+                                       lowest_name=res.files[b].name;
+                               }
+                       }
+                       if(lowest_index!=a){
+                               b=res.files[a];
+                               res.files[a]=res.files[lowest_index];
+                               res.files[lowest_index]=b;
+                       }
+               }
+       }
+       for(a=0;a<res.files.length;++a)wrapper.fileids[a]=res.files[a].id;
+       document.title='File Manager: '+res.reqdir;
+       kfm_lastClicked=null;
+       kfm_log(kfm.lang.FilesRefreshed);
+       if(res.uploads_allowed)kfm_addPanel('kfm_left_column','kfm_file_upload_panel');
+       else kfm_removePanel('kfm_left_column','kfm_file_upload_panel');
+       kfm_refreshPanels('kfm_left_column');
+       if(!res.files.length){
+               $j('#documents_loader').empty().html('&nbsp;');
+               kfm.addEl(wrapper,(new Element('span',{
+                       'class':'kfm_empty'
+               })).setHTML(kfm.lang.DirEmpty(res.reqdir)));
+        }else{
+               if(kfm_listview){
+                       var listview_table=new Element('table',{
+                               'id':'kfm_files_listview_table'
+                       });
+                       wrapper.appendChild(listview_table);
+                       $j(listview_table).html('<thead><tr class="listview_headers"><th>&nbsp;</th><th>Name</th><th style="width:72px">Size</th><th style="width:72px">Type</th><th style="width:142px">Modified</th></tr></thead><tbody></tbody>');
+                               $j(listview_table).css('width','99%');
+               }
+               kfm_incrementalFileDisplay();
+       }
+}
+function kfm_removeFilesFromView(files){
+       kfm_selectNone();
+       if($type(files)!='array' || !files.length)return;
+       var i=0,right_column=$('documents_body');
+       for(var i=0;i<files.length;++i){
+               var el=$('kfm_file_icon_'+files[i]);
+               if(el){
+                       if(kfm_listview){
+                                                       el.parentNode.parentNode.remove();
+                                                       var trows=$ES('#kfm_files_listview_table tr');
+                                               }
+                       else el.remove();
+               }
+               right_column.fileids.remove(files[i]);
+       }
+       kfm_files_reflowIcons();
+}
+function kfm_renameFile(id){
+       var filename=File_getInstance(id).name;
+       kfm_prompt(kfm.lang.RenameFileToWhat(filename),filename,function(newName){
+               if(!newName||newName==filename)return;
+               kfm_log(kfm.lang.RenamedFile(filename,newName));
+               x_kfm_renameFile(id,newName,kfm_refreshFiles);
+       });
+}
+function kfm_renameFiles(nameTemplate){
+       if(nameTemplate && nameTemplate.toString()!==nameTemplate)nameTemplate='';
+       var ok=false;
+       kfm_prompt(kfm.lang.HowWouldYouLikeToRenameTheseFiles,nameTemplate,function(nameTemplate){
+               var asterisks=nameTemplate.replace(/[^*]/g,'').length;
+               if(!nameTemplate)return;
+               if(!/\*/.test(nameTemplate))alert(kfm.lang.YouMustPlaceTheWildcard);
+               else if(/\*[^*]+\*/.test(nameTemplate))alert(kfm.lang.IfYouUseMultipleWildcards);
+               else if(asterisks<(''+selectedFiles.length).length)alert(kfm.lang.YouNeedMoreThan(asterisks,selectedFiles.length));
+               else ok=true;
+               if(!ok)return kfm_renameFiles(nameTemplate);
+               x_kfm_renameFiles(selectedFiles,nameTemplate,kfm_refreshFiles);
+       });
+}
+function kfm_showFileDetails(id){
+       var res=File_getInstance(id);
+       var fd=$('kfm_file_details_panel'),el=$('kfm_left_column');
+               if(!el)return false;
+       if(!fd){
+               kfm_addPanel('kfm_left_column','kfm_file_details_panel');
+               kfm_refreshPanels(el);
+       }
+       var body=$E('#kfm_file_details_panel div.kfm_panel_body').empty();
+       if(!res){
+               body.innerHTML=kfm.lang.NoFilesSelected;
+               return;
+       }
+       var table=kfm_buildFileDetailsTable(res);
+       kfm.addEl(body,table);
+}
+function kfm_showToolTip(id){
+       if(!id || kfm_listview)return;
+       var F=File_getInstance(id);
+       var table=kfm_buildFileDetailsTable(F),icon=$('kfm_file_icon_'+id);
+       if(!icon||contextmenu)return;
+       table.id='kfm_tooltip';
+       kfm.addEl(document.body,table);
+       var l=getOffset(icon,'Left'),t=getOffset(icon,'Top'),w=icon.offsetWidth,h=icon.offsetHeight,ws=window.getSize().size;
+       l=(l+(w/2)>ws.x/2)?l-table.offsetWidth:l+w;
+       table.setStyles('position:absolute;top:'+t+'px;left:'+l+'px;visibility:visible;opacity:.9');
+}
+function kfm_zip(name){
+       if(!name || name.toString()!==name)name='zipped.zip';
+       var ok=false;
+       kfm_prompt(kfm.lang.WhatFilenameDoYouWantToUse,name,function(name){
+               if(!name)return;
+               if(/\.zip$/.test(name))ok=true;
+               else kfm.alert(kfm.lang.TheFilenameShouldEndWithN('.zip'));
+               if(!ok)return kfm_zip(name);
+               x_kfm_zip(name,selectedFiles,kfm_refreshFiles);
+       });
+}
+function kfm_fileLoader(id){
+       if($type(id)!='array')return $j('#kfm_file_icon_'+id).css('background-image','url(themes/'+kfm_theme+'/icons/64x64/loader.gif)');
+       id.each(kfm_fileLoader);
+}
+function kfm_filesLoader(){
+       $j('<img src="themes/'+kfm_theme+'/small_loader.gif" alt=""/>').appendTo('#documents_loader');
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/hooks.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/hooks.js
new file mode 100644 (file)
index 0000000..c883c82
--- /dev/null
@@ -0,0 +1,160 @@
+/* begin core section */
+
+/* define the order of the categories */
+var HookCategories=["main", "view", "edit", "returning"];
+
+var kfm_imageExtensions=['jpg','png','gif'];
+/* initialize arrays */
+var HooksSingleReadonly={};
+var HooksSingleWritable={};
+var HooksMultiple={};
+function kfm_addHook(objoriginal, properties){
+       var obj=objoriginal;
+       /*Write properties to object, so they can be different for each call*/
+       if(properties){
+               if(typeof(properties.doFunction)!="undefined"){
+                       if(typeof(properties.doFunction)=="function")obj.doFunction=properties.doFunction;
+                       if(typeof(properties.doFunction)=="string")obj.doFunction=eval('obj.'+properties.doFunction+';');
+               }
+               if(typeof(properties.mode)!="undefined")obj.mode=properties.mode;
+               if(typeof(properties.title)!="undefined")obj.title=properties.title;
+               if(typeof(properties.name)!="undefined")obj.name=properties.name;
+               if(typeof(properties.category)!="undefined")obj.category=properties.category;
+               if(typeof(properties.defaultOpener)!="undefined")obj.defaultOpener=properties.defaultOpener;
+               if(typeof(properties.writable)!="undefined")obj.writable=properties.writable;
+               if(typeof(properties.extensions)!="undefined")obj.extensions=properties.extensions;
+       }
+       if(typeof(obj.name)=="undefined"&&typeof(obj.title)!="undefined")obj.name=obj.title; // make sure the plugin has a name
+       if(typeof(obj.category)=="undefined")obj.category=HookCategories[0]; // Without category, place in the top category
+       if(!obj.extensions)obj.extensions="all";
+
+       if(!kfm_vars.permissions.file.ed && obj.category=='edit')return;
+       if(!kfm_vars.permissions.image.manip && obj.category=='edit'){
+               if(obj.extensions=='all')return;
+               //remove unwanted extension (image extensions)
+               for(var i=0; i<obj.extensions.length; i++){
+                       for(var j=0; j<kfm_imageExtensions.length; j++){
+                               if(obj.extensions[i]==kfm_imageExtensions[j]){
+                                       obj.extensions.splice(i,1);
+                                       return;
+                               }
+                       }
+               }
+       }
+
+       if(obj.mode==0 || obj.mode==2){
+               /*single file*/
+               if(obj.writable==1 || obj.writable==2)kfm_addHookToArray(obj,"HooksSingleWritable");
+               if(obj.writable==0 || obj.writable==2)kfm_addHookToArray(obj,"HooksSingleReadonly");
+       }
+       if(obj.mode==1 || obj.mode==2){
+               /*selection of multiple files*/
+               kfm_addHookToArray(obj,"HooksMultiple");
+       }
+}
+function kfm_addHookToArray(obj, HooksArray){
+       /* Add the hook object to the proper array */
+       if(!obj.extensions)return false;
+       if(typeof(obj.extensions)=="string" && obj.extensions.toLowerCase()=="all" || HooksArray=="HooksMultiple"){
+               ext="all";
+               if(eval("typeof("+HooksArray+'.'+ext+')=="undefined"'))kfm_addHookExtension(HooksArray, ext);
+               if(eval("typeof("+HooksArray+'.'+ext+'.'+obj.category+')=="undefined"'))kfm_addHookCategory(HooksArray, ext, obj.category);
+               eval(HooksArray+'.'+ext+'.'+obj.category+'.push(obj);');
+       }else{
+               for(var i=0;i<obj.extensions.length; i++){
+                       ext=obj.extensions[i];
+                       if(eval("typeof("+HooksArray+'.'+ext+')=="undefined"'))kfm_addHookExtension(HooksArray, ext);
+                       if(eval("typeof("+HooksArray+'.'+ext+'.'+obj.category+')=="undefined"'))kfm_addHookCategory(HooksArray, ext, obj.category);
+                       eval(HooksArray+'.'+ext+'.'+obj.category+'.push(obj);');
+               }
+       }
+}
+function kfm_addHookExtension(HooksArray, ext){
+       eval(HooksArray+'.'+ext+'={};');
+}
+function kfm_addHookCategory(HookArray,ext, newCategory){
+       /*Add a hook category and*/
+       eval(HookArray+'.'+ext+'.'+newCategory+'=[];');
+}
+function kfm_getLinks(files){
+       /**
+        * initial return function 
+        * category information is lost but order of category is maintained 
+        */
+       var HooksArray="";//initialize
+
+       /* multiple file section */
+       var cPlugins=[];
+       function addPlugin(plugin, fid){
+               var add=true;
+               /* determine index and add plugin if is not present */
+               var index=-1;
+               for(var i=0;i<cPlugins.length;i++){
+                       if(cPlugins[i].name==plugin.name){
+                               add=false;
+                               index=i;
+                               break;
+                       }
+               }
+               if(add){
+                       cPlugins.push(plugin);
+                       index=cPlugins.length-1;
+                       cPlugins[index].doParameter=[];
+               }
+       
+               /* Then add the file id to the doParameter */
+               cPlugins[index].doParameter.push(fid);
+       }
+       if(files.length>1){
+               for(var i=0; i<files.length; i++){
+                       var F=File_getInstance(files[i]);
+         var extension=F.name.replace(/.*\./,'').toLowerCase();
+                       for(var k=0;k<HookCategories.length; k++){
+                               if(eval('HooksMultiple.all.'+HookCategories[k]))plugins=eval('HooksMultiple.all.'+HookCategories[k]);
+                               else plugins=[];
+                               for(var j=0; j<plugins.length; j++){ // loop over plugins
+                                       var plugin=plugins[j];
+                                       if(     F.writable && 
+                                                       (plugin.writable==1 || plugin.writable==2) && 
+                                                       ((typeof(plugin.extensions)=="string" && plugin.extensions=="all") || plugin.extensions.indexOf(extension)!=-1)
+                                               )
+                                               addPlugin(plugin,F.id);
+                                       else if(        !F.writable && 
+                                                       (plugin.writable==0 || plugin.writable==2) && 
+                                                       ((typeof(plugin.extensions)=="string" && plugin.extensions=="all") || plugin.extensions.indexOf(extension)!=-1)
+                                               )
+                                               addPlugin(plugin,F.id);
+                               }
+                       }
+               }
+               return cPlugins;
+       }
+
+       /* single file section */
+       var hookObjects=[];
+       var F=File_getInstance(files[0]);
+       var ext=F.ext;
+       if(F.writable)HooksArray="HooksSingleWritable";
+       else HooksArray="HooksSingleReadonly";
+
+       for(var j=0;j<HookCategories.length;j++){
+               category=HookCategories[j];
+               /* extend is a mootools function*/
+               if(typeof(eval(HooksArray+'.all.'+category))!='undefined')hookObjects.extend(eval(HooksArray+'.all.'+category));
+               try{
+                       if(typeof(eval(HooksArray+'.'+ext+'.'+category))!='undefined')hookObjects.extend(eval(HooksArray+'.'+ext+'.'+category));
+               }
+               catch(e){ // unknown extension
+               }
+       }
+       hookObjects.forEach(function(item, index){
+               item.doParameter=[F.id];
+       });
+       return hookObjects;
+}
+function kfm_getDefaultOpener(id){
+       var hooks=kfm_getLinks([id]);
+       for(var i=0;i<hooks.length;++i){
+               if(hooks[i].defaultOpener)return hooks[i];
+       }
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/images.and.icons.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/images.and.icons.js
new file mode 100644 (file)
index 0000000..4c01376
--- /dev/null
@@ -0,0 +1,102 @@
+// see ../license.txt for licensing
+function kfm_changeCaption(id){
+       kfm_prompt(kfm.lang.ChangeCaption,File_getInstance(id).caption,function(newCaption){
+               x_kfm_changeCaption(id,newCaption,function(res){
+                       File_getInstance(id).caption=newCaption;
+               });
+       });
+       /*
+       var table=$extend(new Element('table',{
+               'id':'kfm_newCaptionDetails'
+       }),{kfm_caption_for:id});
+       var row=table.insertRow(0),textarea=newInput('kfm_new_caption','textarea',File_getInstance(id).caption);
+       textarea.setStyles('height:50px;width:200px');
+       row.insertCell(0).appendChild(newText(kfm.lang.NewCaption));
+       row.insertCell(1).appendChild(textarea);
+       kfm_modal_open(table,kfm.lang.ChangeCaption,[[kfm.lang.ChangeCaption,kfm_changeCaption_set]]);
+       $('kfm_new_caption').focus();
+       */
+}
+function kfm_changeCaption_set(){
+       var id=$('kfm_newCaptionDetails').kfm_caption_for,newCaption=$('kfm_new_caption').value;
+       if(!newCaption||newCaption==File_getInstance(id).caption)return;
+       kfm_modal_close();
+       if(kfm.confirm(kfm.lang.NewCaptionIsThisCorrect(newCaption))){
+               kfm_log(kfm.lang.Log_ChangeCaption(id,newCaption));
+               x_kfm_changeCaption(id,newCaption,kfm_refreshFiles);
+       }
+}
+function kfm_resizeImage(id){
+       var data=File_getInstance(id);
+       var txt=kfm.lang.CurrentSize(data.width,data.height);
+       kfm_prompt(txt+kfm.lang.NewWidth,data.width,function(x){
+               x=parseInt(x);
+               if(!x)return;
+               txt+=kfm.lang.NewWidthConfirmTxt(x);
+               kfm_prompt(txt+kfm.lang.NewHeight,Math.ceil(data.height*(x/data.width)),function(y){
+                       y=parseInt(y);
+                       if(!y)return;
+                       if(kfm.confirm(txt+kfm.lang.NewHeightConfirmTxt(y)))x_kfm_resizeImage(id,x,y,kfm_refreshFiles);
+               });
+       });
+}
+/* should have been moved to the cropper plugin
+function kfm_cropImage(id){
+       var data=File_getInstance(id);
+       var div=document.createElement('DIV');
+       div.style.position='absolute';
+       div.id='cropperdiv';
+       div.style.top=0;
+       div.style.left=0;
+       div.style.width='100%';
+       div.style.height='100%';
+       div.style.backgroundColor='#ddf';
+       div.onclick=function(){this.style.display='none';}
+
+       var ifr = document.createElement('IFRAME');
+       ifr.src = 'plugins/cropper/croparea.php?id='+id+'&width='+data.width+'&height='+data.height;
+       ifr.style.width = '100%';
+       ifr.style.height = '100%'; //100% - 25px
+       div.appendChild(ifr);
+       document.body.appendChild(div);
+}
+function kfm_cropToOriginal(id,coords,dimensions){
+       var F=File_getInstance(id);
+       document.getElementById('cropperdiv').style.display = 'none';
+       x_kfm_cropToOriginal(id, coords.x1, coords.y1, dimensions.width, dimensions.height, function(id){
+               if($type(id)=='string')return kfm_log(id);
+               F.setThumbnailBackground($('kfm_file_icon_'+id),true);
+       });
+}
+function kfm_cropToNew(id, coords, dimensions){
+       var filename=File_getInstance(id).name;
+       kfm_prompt(kfm.lang.RenameFileToWhat(filename),filename,function(newName){
+               if(!newName||newName==filename)return;
+               document.getElementById('cropperdiv').style.display = 'none';
+               x_kfm_cropToNew(id, coords.x1, coords.y1, dimensions.width, dimensions.height, newName, kfm_refreshFiles);
+       });
+}
+*/
+function kfm_returnThumbnail(id,size){
+       if(!size)size='64x64';
+       valid=1;
+       kfm_prompt(kfm.lang.WhatMaximumSize,size,function(size){
+               if(!size)return;
+               if(!/^[0-9]+x[0-9]+$/.test(size)){
+                       alert('The size must be in the format XXxYY, where X is the width and Y is the height');
+                       valid=0;
+               }
+               if(!valid)return kfm_returnThumbnail(id,size);
+               var x=size.replace(/x.*/,''),y=size.replace(/.*x/,'');
+               x_kfm_getFileUrl(id,x,y,function(url){
+                       if(kfm_file_handler=='return'||kfm_file_handler=='fckeditor'){
+                               window.opener.SetUrl(url,0,0,File_getInstance(id).caption);
+                               window.close();
+                       }
+                       else if(kfm_file_handler=='download'){
+                               if(/get.php/.test(url))url+='&forcedownload=1';
+                               document.location=url;
+                       }
+               });
+       });
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/all.php b/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/all.php
new file mode 100644 (file)
index 0000000..e8e1918
--- /dev/null
@@ -0,0 +1,12 @@
+<?php
+$js=file_get_contents('jquery-1.2.2.pack.js');
+$js.=file_get_contents('jquery.dimensions.pack.js');
+$js.=file_get_contents('jquery.impromptu.js');
+$js.=file_get_contents('jquery.iutil.pack.js');
+$js.=file_get_contents('jquery.idrag.js');
+$js.=file_get_contents('jquery.grid.columnSizing.js');
+//$js.=file_get_contents('jquery.tablesorter.pack.js');
+$js.=file_get_contents('jquery.tablesorter.js');
+header ('Content-type: text/javascript');
+header('Expires: '.gmdate("D, d M Y H:i:s", time() + 3600*24*365).' GMT');
+echo $js;
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery-1.2.2.pack.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery-1.2.2.pack.js
new file mode 100644 (file)
index 0000000..ba67ea9
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * jQuery 1.2.2 - New Wave Javascript
+ *
+ * Copyright (c) 2007 John Resig (jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2008-01-14 17:56:07 -0500 (Mon, 14 Jan 2008) $
+ * $Rev: 4454 $
+ */
+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(J(){7(1e.19)L w=1e.19;L E=1e.19=J(a,b){K 1D E.2m.4Y(a,b)};7(1e.$)L D=1e.$;1e.$=E;L u=/^[^<]*(<(.|\\s)+>)[^>]*$|^#(\\w+)$/;L G=/^.[^:#\\[\\.]*$/;E.1i=E.2m={4Y:J(d,b){d=d||T;7(d.15){6[0]=d;6.M=1;K 6}N 7(1v d=="25"){L c=u.39(d);7(c&&(c[1]||!b)){7(c[1])d=E.5c([c[1]],b);N{L a=T.5N(c[3]);7(a)7(a.2s!=c[3])K E().2r(d);N{6[0]=a;6.M=1;K 6}N d=[]}}N K 1D E(b).2r(d)}N 7(E.1q(d))K 1D E(T)[E.1i.21?"21":"43"](d);K 6.6G(d.1n==1N&&d||(d.5j||d.M&&d!=1e&&!d.15&&d[0]!=10&&d[0].15)&&E.2H(d)||[d])},5j:"1.2.2",82:J(){K 6.M},M:0,22:J(a){K a==10?E.2H(6):6[a]},2E:J(b){L a=E(b);a.56=6;K a},6G:J(a){6.M=0;1N.2m.1h.1j(6,a);K 6},V:J(a,b){K E.V(6,a,b)},5E:J(b){L a=-1;6.V(J(i){7(6==b)a=i});K a},1K:J(c,a,b){L d=c;7(c.1n==4d)7(a==10)K 6.M&&E[b||"1K"](6[0],c)||10;N{d={};d[c]=a}K 6.V(J(i){P(c 1r d)E.1K(b?6.Y:6,c,E.1l(6,d[c],b,i,c))})},1m:J(b,a){7((b==\'29\'||b==\'1P\')&&2M(a)<0)a=10;K 6.1K(b,a,"2q")},1t:J(b){7(1v b!="4D"&&b!=W)K 6.4B().3t((6[0]&&6[0].2u||T).5v(b));L a="";E.V(b||6,J(){E.V(6.3p,J(){7(6.15!=8)a+=6.15!=1?6.6M:E.1i.1t([6])})});K a},5r:J(b){7(6[0])E(b,6[0].2u).5J().3n(6[0]).2a(J(){L a=6;2e(a.1B)a=a.1B;K a}).3t(6);K 6},8t:J(a){K 6.V(J(){E(6).6C().5r(a)})},8m:J(a){K 6.V(J(){E(6).5r(a)})},3t:J(){K 6.3P(1a,R,S,J(a){7(6.15==1)6.3k(a)})},6s:J(){K 6.3P(1a,R,R,J(a){7(6.15==1)6.3n(a,6.1B)})},6o:J(){K 6.3P(1a,S,S,J(a){6.1b.3n(a,6)})},5a:J(){K 6.3P(1a,S,R,J(a){6.1b.3n(a,6.2J)})},3h:J(){K 6.56||E([])},2r:J(b){L c=E.2a(6,J(a){K E.2r(b,a)});K 6.2E(/[^+>] [^+>]/.17(b)||b.1g("..")>-1?E.57(c):c)},5J:J(e){L f=6.2a(J(){7(E.14.1d&&!E.3W(6)){L a=6.6c(R),5u=T.2R("1u"),4T=T.2R("1u");5u.3k(a);4T.38=5u.38;K 4T.1B}N K 6.6c(R)});L d=f.2r("*").4R().V(J(){7(6[F]!=10)6[F]=W});7(e===R)6.2r("*").4R().V(J(i){7(6.15==3)K;L c=E.Q(6,"2N");P(L a 1r c)P(L b 1r c[a])E.16.1c(d[i],a,c[a][b],c[a][b].Q)});K f},1F:J(b){K 6.2E(E.1q(b)&&E.3x(6,J(a,i){K b.1O(a,i)})||E.3d(b,6))},4I:J(b){7(b.1n==4d)7(G.17(b))K 6.2E(E.3d(b,6,R));N b=E.3d(b,6);L a=b.M&&b[b.M-1]!==10&&!b.15;K 6.1F(J(){K a?E.35(6,b)<0:6!=b})},1c:J(a){K!a?6:6.2E(E.34(6.22(),a.1n==4d?E(a).22():a.M!=10&&(!a.12||E.12(a,"3i"))?a:[a]))},3K:J(a){K a?E.3d(a,6).M>0:S},7g:J(a){K 6.3K("."+a)},5P:J(b){7(b==10){7(6.M){L c=6[0];7(E.12(c,"2y")){L e=c.44,5L=[],11=c.11,30=c.U=="2y-30";7(e<0)K W;P(L i=30?e:0,2b=30?e+1:11.M;i<2b;i++){L d=11[i];7(d.2p){b=E.14.1d&&!d.9s.1C.9o?d.1t:d.1C;7(30)K b;5L.1h(b)}}K 5L}N K(6[0].1C||"").1p(/\\r/g,"")}K 10}K 6.V(J(){7(6.15!=1)K;7(b.1n==1N&&/5w|5y/.17(6.U))6.3o=(E.35(6.1C,b)>=0||E.35(6.37,b)>=0);N 7(E.12(6,"2y")){L a=b.1n==1N?b:[b];E("90",6).V(J(){6.2p=(E.35(6.1C,a)>=0||E.35(6.1t,a)>=0)});7(!a.M)6.44=-1}N 6.1C=b})},3q:J(a){K a==10?(6.M?6[0].38:W):6.4B().3t(a)},6P:J(a){K 6.5a(a).1Y()},6N:J(i){K 6.2V(i,i+1)},2V:J(){K 6.2E(1N.2m.2V.1j(6,1a))},2a:J(b){K 6.2E(E.2a(6,J(a,i){K b.1O(a,i,a)}))},4R:J(){K 6.1c(6.56)},3P:J(g,f,h,d){L e=6.M>1,3m;K 6.V(J(){7(!3m){3m=E.5c(g,6.2u);7(h)3m.8I()}L b=6;7(f&&E.12(6,"1V")&&E.12(3m[0],"4x"))b=6.3V("1S")[0]||6.3k(6.2u.2R("1S"));L c=E([]);E.V(3m,J(){L a=e?E(6).5J(R)[0]:6;7(E.12(a,"1o")){c=c.1c(a)}N{7(a.15==1)c=c.1c(E("1o",a).1Y());d.1O(b,a)}});c.V(6D)})}};E.2m.4Y.2m=E.2m;J 6D(i,a){7(a.3R)E.3Q({1f:a.3R,3l:S,1G:"1o"});N E.5l(a.1t||a.6A||a.38||"");7(a.1b)a.1b.2X(a)}E.1s=E.1i.1s=J(){L b=1a[0]||{},i=1,M=1a.M,5i=S,11;7(b.1n==8f){5i=b;b=1a[1]||{};i=2}7(1v b!="4D"&&1v b!="J")b={};7(M==1){b=6;i=0}P(;i<M;i++)7((11=1a[i])!=W)P(L a 1r 11){7(b===11[a])6z;7(5i&&11[a]&&1v 11[a]=="4D"&&b[a]&&!11[a].15)b[a]=E.1s(b[a],11[a]);N 7(11[a]!=10)b[a]=11[a]}K b};L F="19"+(1D 3O()).3N(),6y=0,5e={};L H=/z-?5E|89-?87|1y|6q|85-?1P/i;E.1s({81:J(a){1e.$=D;7(a)1e.19=w;K E},1q:J(a){K!!a&&1v a!="25"&&!a.12&&a.1n!=1N&&/J/i.17(a+"")},3W:J(a){K a.1I&&!a.1k||a.28&&a.2u&&!a.2u.1k},5l:J(a){a=E.3f(a);7(a){L b=T.3V("6k")[0]||T.1I,1o=T.2R("1o");1o.U="1t/4l";7(E.14.1d)1o.1t=a;N 1o.3k(T.5v(a));b.3k(1o);b.2X(1o)}},12:J(b,a){K b.12&&b.12.2F()==a.2F()},1Q:{},Q:J(c,d,b){c=c==1e?5e:c;L a=c[F];7(!a)a=c[F]=++6y;7(d&&!E.1Q[a])E.1Q[a]={};7(b!=10)E.1Q[a][d]=b;K d?E.1Q[a][d]:a},3H:J(c,b){c=c==1e?5e:c;L a=c[F];7(b){7(E.1Q[a]){2T E.1Q[a][b];b="";P(b 1r E.1Q[a])1T;7(!b)E.3H(c)}}N{1R{2T c[F]}1W(e){7(c.55)c.55(F)}2T E.1Q[a]}},V:J(c,a,b){7(b){7(c.M==10){P(L d 1r c)7(a.1j(c[d],b)===S)1T}N P(L i=0,M=c.M;i<M;i++)7(a.1j(c[i],b)===S)1T}N{7(c.M==10){P(L d 1r c)7(a.1O(c[d],d,c[d])===S)1T}N P(L i=0,M=c.M,1C=c[0];i<M&&a.1O(1C,i,1C)!==S;1C=c[++i]){}}K c},1l:J(b,a,c,i,d){7(E.1q(a))a=a.1O(b,i);K a&&a.1n==53&&c=="2q"&&!H.17(d)?a+"2P":a},1w:{1c:J(c,b){E.V((b||"").2d(/\\s+/),J(i,a){7(c.15==1&&!E.1w.3E(c.1w,a))c.1w+=(c.1w?" ":"")+a})},1Y:J(c,b){7(c.15==1)c.1w=b!=10?E.3x(c.1w.2d(/\\s+/),J(a){K!E.1w.3E(b,a)}).6g(" "):""},3E:J(b,a){K E.35(a,(b.1w||b).3D().2d(/\\s+/))>-1}},6e:J(b,c,a){L e={};P(L d 1r c){e[d]=b.Y[d];b.Y[d]=c[d]}a.1O(b);P(L d 1r c)b.Y[d]=e[d]},1m:J(d,e,c){7(e=="29"||e=="1P"){L b,3S={3C:"4Z",4X:"23",18:"3u"},3r=e=="29"?["7P","7M"]:["7L","7K"];J 4S(){b=e=="29"?d.7J:d.7I;L a=0,3a=0;E.V(3r,J(){a+=2M(E.2q(d,"7H"+6,R))||0;3a+=2M(E.2q(d,"3a"+6+"62",R))||0});b-=1Z.7E(a+3a)}7(E(d).3K(":4b"))4S();N E.6e(d,3S,4S);K 1Z.2b(0,b)}K E.2q(d,e,c)},2q:J(e,k,j){L d;J 3y(b){7(!E.14.26)K S;L a=T.4a.4L(b,W);K!a||a.4K("3y")==""}7(k=="1y"&&E.14.1d){d=E.1K(e.Y,"1y");K d==""?"1":d}7(E.14.2B&&k=="18"){L c=e.Y.18;e.Y.18="3u";e.Y.18=c}7(k.1E(/4c/i))k=y;7(!j&&e.Y&&e.Y[k])d=e.Y[k];N 7(T.4a&&T.4a.4L){7(k.1E(/4c/i))k="4c";k=k.1p(/([A-Z])/g,"-$1").2w();L h=T.4a.4L(e,W);7(h&&!3y(e))d=h.4K(k);N{L f=[],2L=[];P(L a=e;a&&3y(a);a=a.1b)2L.4U(a);P(L i=0;i<2L.M;i++)7(3y(2L[i])){f[i]=2L[i].Y.18;2L[i].Y.18="3u"}d=k=="18"&&f[2L.M-1]!=W?"2D":(h&&h.4K(k))||"";P(L i=0;i<f.M;i++)7(f[i]!=W)2L[i].Y.18=f[i]}7(k=="1y"&&d=="")d="1"}N 7(e.4j){L g=k.1p(/\\-(\\w)/g,J(a,b){K b.2F()});d=e.4j[k]||e.4j[g];7(!/^\\d+(2P)?$/i.17(d)&&/^\\d/.17(d)){L l=e.Y.2c,3A=e.3A.2c;e.3A.2c=e.4j.2c;e.Y.2c=d||0;d=e.Y.7l+"2P";e.Y.2c=l;e.3A.2c=3A}}K d},5c:J(l,h){L k=[];h=h||T;7(1v h.2R==\'10\')h=h.2u||h[0]&&h[0].2u||T;E.V(l,J(i,d){7(!d)K;7(d.1n==53)d=d.3D();7(1v d=="25"){d=d.1p(/(<(\\w+)[^>]*?)\\/>/g,J(b,a,c){K c.1E(/^(7k|7h|5Q|7f|48|5O|a3|3v|9Y|9W|9T)$/i)?b:a+"></"+c+">"});L f=E.3f(d).2w(),1u=h.2R("1u");L e=!f.1g("<9R")&&[1,"<2y 78=\'78\'>","</2y>"]||!f.1g("<9O")&&[1,"<77>","</77>"]||f.1E(/^<(9K|1S|9I|9F|9A)/)&&[1,"<1V>","</1V>"]||!f.1g("<4x")&&[2,"<1V><1S>","</1S></1V>"]||(!f.1g("<9y")||!f.1g("<9v"))&&[3,"<1V><1S><4x>","</4x></1S></1V>"]||!f.1g("<5Q")&&[2,"<1V><1S></1S><76>","</76></1V>"]||E.14.1d&&[1,"1u<1u>","</1u>"]||[0,"",""];1u.38=e[1]+d+e[2];2e(e[0]--)1u=1u.5D;7(E.14.1d){L g=!f.1g("<1V")&&f.1g("<1S")<0?1u.1B&&1u.1B.3p:e[1]=="<1V>"&&f.1g("<1S")<0?1u.3p:[];P(L j=g.M-1;j>=0;--j)7(E.12(g[j],"1S")&&!g[j].3p.M)g[j].1b.2X(g[j]);7(/^\\s/.17(d))1u.3n(h.5v(d.1E(/^\\s*/)[0]),1u.1B)}d=E.2H(1u.3p)}7(d.M===0&&(!E.12(d,"3i")&&!E.12(d,"2y")))K;7(d[0]==10||E.12(d,"3i")||d.11)k.1h(d);N k=E.34(k,d)});K k},1K:J(d,e,c){7(!d||d.15==3||d.15==8)K 10;L f=E.3W(d)?{}:E.3S;7(e=="2p"&&E.14.26)d.1b.44;7(f[e]){7(c!=10)d[f[e]]=c;K d[f[e]]}N 7(E.14.1d&&e=="Y")K E.1K(d.Y,"9r",c);N 7(c==10&&E.14.1d&&E.12(d,"3i")&&(e=="9q"||e=="9p"))K d.9n(e).6M;N 7(d.28){7(c!=10){7(e=="U"&&E.12(d,"48")&&d.1b)6Z"U 9i 9g\'t 9b 9a";d.99(e,""+c)}7(E.14.1d&&/6T|3R/.17(e)&&!E.3W(d))K d.4z(e,2);K d.4z(e)}N{7(e=="1y"&&E.14.1d){7(c!=10){d.6q=1;d.1F=(d.1F||"").1p(/6W\\([^)]*\\)/,"")+(2M(c).3D()=="93"?"":"6W(1y="+c*6S+")")}K d.1F&&d.1F.1g("1y=")>=0?(2M(d.1F.1E(/1y=([^)]*)/)[1])/6S).3D():""}e=e.1p(/-([a-z])/92,J(a,b){K b.2F()});7(c!=10)d[e]=c;K d[e]}},3f:J(a){K(a||"").1p(/^\\s+|\\s+$/g,"")},2H:J(b){L a=[];7(1v b!="91")P(L i=0,M=b.M;i<M;i++)a.1h(b[i]);N a=b.2V(0);K a},35:J(b,a){P(L i=0,M=a.M;i<M;i++)7(a[i]==b)K i;K-1},34:J(a,b){7(E.14.1d){P(L i=0;b[i];i++)7(b[i].15!=8)a.1h(b[i])}N P(L i=0;b[i];i++)a.1h(b[i]);K a},57:J(a){L c=[],2j={};1R{P(L i=0,M=a.M;i<M;i++){L b=E.Q(a[i]);7(!2j[b]){2j[b]=R;c.1h(a[i])}}}1W(e){c=a}K c},3x:J(c,a,d){7(1v a=="25")a=4A("S||J(a,i){K "+a+"}");L b=[];P(L i=0,M=c.M;i<M;i++)7(!d&&a(c[i],i)||d&&!a(c[i],i))b.1h(c[i]);K b},2a:J(d,a){L c=[];P(L i=0,M=d.M;i<M;i++){L b=a(d[i],i);7(b!==W&&b!=10){7(b.1n!=1N)b=[b];c=c.6Q(b)}}K c}});L v=8X.8V.2w();E.14={5n:(v.1E(/.+(?:8R|8Q|8P|8O)[\\/: ]([\\d.]+)/)||[])[1],26:/6L/.17(v),2B:/2B/.17(v),1d:/1d/.17(v)&&!/2B/.17(v),3X:/3X/.17(v)&&!/(8M|6L)/.17(v)};L y=E.14.1d?"6K":"6J";E.1s({8J:!E.14.1d||T.6I=="6H",3S:{"P":"8G","8E":"1w","4c":y,6J:y,6K:y,38:"38",1w:"1w",1C:"1C",2W:"2W",3o:"3o",8C:"8B",2p:"2p",8A:"8z",44:"44",6F:"6F",28:"28",12:"12"}});E.V({6E:"O.1b",8y:"19.4w(O,\'1b\')",8x:"19.31(O,2,\'2J\')",8w:"19.31(O,2,\'4v\')",8v:"19.4w(O,\'2J\')",8u:"19.4w(O,\'4v\')",8s:"19.5m(O.1b.1B,O)",8r:"19.5m(O.1B)",6C:"19.12(O,\'8q\')?O.8p||O.8o.T:19.2H(O.3p)"},J(c,d){d=4A("S||J(O){K "+d+"}");E.1i[c]=J(b){L a=E.2a(6,d);7(b&&1v b=="25")a=E.3d(b,a);K 6.2E(E.57(a))}});E.V({6B:"3t",8n:"6s",3n:"6o",8l:"5a",8k:"6P"},J(c,b){E.1i[c]=J(){L a=1a;K 6.V(J(){P(L i=0,M=a.M;i<M;i++)E(a[i])[b](6)})}});E.V({8j:J(a){E.1K(6,a,"");7(6.15==1)6.55(a)},8i:J(a){E.1w.1c(6,a)},8h:J(a){E.1w.1Y(6,a)},8g:J(a){E.1w[E.1w.3E(6,a)?"1Y":"1c"](6,a)},1Y:J(a){7(!a||E.1F(a,[6]).r.M){E("*",6).1c(6).V(J(){E.16.1Y(6);E.3H(6)});7(6.1b)6.1b.2X(6)}},4B:J(){E(">*",6).1Y();2e(6.1B)6.2X(6.1B)}},J(a,b){E.1i[a]=J(){K 6.V(b,1a)}});E.V(["8e","62"],J(i,c){L b=c.2w();E.1i[b]=J(a){K 6[0]==1e?E.14.2B&&T.1k["5h"+c]||E.14.26&&1e["8d"+c]||T.6I=="6H"&&T.1I["5h"+c]||T.1k["5h"+c]:6[0]==T?1Z.2b(1Z.2b(T.1k["5g"+c],T.1I["5g"+c]),1Z.2b(T.1k["5f"+c],T.1I["5f"+c])):a==10?(6.M?E.1m(6[0],b):W):6.1m(b,a.1n==4d?a:a+"2P")}});L C=E.14.26&&4t(E.14.5n)<8c?"(?:[\\\\w*4s-]|\\\\\\\\.)":"(?:[\\\\w\\8b-\\8a*4s-]|\\\\\\\\.)",6w=1D 4r("^>\\\\s*("+C+"+)"),6v=1D 4r("^("+C+"+)(#)("+C+"+)"),6u=1D 4r("^([#.]?)("+C+"*)");E.1s({5d:{"":"m[2]==\'*\'||19.12(a,m[2])","#":"a.4z(\'2s\')==m[2]",":":{88:"i<m[3]-0",86:"i>m[3]-0",31:"m[3]-0==i",6N:"m[3]-0==i",3j:"i==0",3M:"i==r.M-1",6r:"i%2==0",6p:"i%2","3j-4m":"a.1b.3V(\'*\')[0]==a","3M-4m":"19.31(a.1b.5D,1,\'4v\')==a","84-4m":"!19.31(a.1b.5D,2,\'4v\')",6E:"a.1B",4B:"!a.1B",83:"(a.6A||a.80||19(a).1t()||\'\').1g(m[3])>=0",4b:\'"23"!=a.U&&19.1m(a,"18")!="2D"&&19.1m(a,"4X")!="23"\',23:\'"23"==a.U||19.1m(a,"18")=="2D"||19.1m(a,"4X")=="23"\',7Y:"!a.2W",2W:"a.2W",3o:"a.3o",2p:"a.2p||19.1K(a,\'2p\')",1t:"\'1t\'==a.U",5w:"\'5w\'==a.U",5y:"\'5y\'==a.U",5b:"\'5b\'==a.U",3J:"\'3J\'==a.U",59:"\'59\'==a.U",6n:"\'6n\'==a.U",6m:"\'6m\'==a.U",2G:\'"2G"==a.U||19.12(a,"2G")\',48:"/48|2y|6l|2G/i.17(a.12)",3E:"19.2r(m[3],a).M",7X:"/h\\\\d/i.17(a.12)",7W:"19.3x(19.3I,J(1i){K a==1i.O;}).M"}},6j:[/^(\\[) *@?([\\w-]+) *([!*$^~=]*) *(\'?"?)(.*?)\\4 *\\]/,/^(:)([\\w-]+)\\("?\'?(.*?(\\(.*?\\))?[^(]*?)"?\'?\\)/,1D 4r("^([:.#]*)("+C+"+)")],3d:J(a,c,b){L d,2o=[];2e(a&&a!=d){d=a;L f=E.1F(a,c,b);a=f.t.1p(/^\\s*,\\s*/,"");2o=b?c=f.r:E.34(2o,f.r)}K 2o},2r:J(t,p){7(1v t!="25")K[t];7(p&&p.15!=1&&p.15!=9)K[];p=p||T;L d=[p],2j=[],3M,12;2e(t&&3M!=t){L r=[];3M=t;t=E.3f(t);L o=S;L g=6w;L m=g.39(t);7(m){12=m[1].2F();P(L i=0;d[i];i++)P(L c=d[i].1B;c;c=c.2J)7(c.15==1&&(12=="*"||c.12.2F()==12))r.1h(c);d=r;t=t.1p(g,"");7(t.1g(" ")==0)6z;o=R}N{g=/^([>+~])\\s*(\\w*)/i;7((m=g.39(t))!=W){r=[];L l={};12=m[2].2F();m=m[1];P(L j=0,3g=d.M;j<3g;j++){L n=m=="~"||m=="+"?d[j].2J:d[j].1B;P(;n;n=n.2J)7(n.15==1){L h=E.Q(n);7(m=="~"&&l[h])1T;7(!12||n.12.2F()==12){7(m=="~")l[h]=R;r.1h(n)}7(m=="+")1T}}d=r;t=E.3f(t.1p(g,""));o=R}}7(t&&!o){7(!t.1g(",")){7(p==d[0])d.4k();2j=E.34(2j,d);r=d=[p];t=" "+t.6i(1,t.M)}N{L k=6v;L m=k.39(t);7(m){m=[0,m[2],m[3],m[1]]}N{k=6u;m=k.39(t)}m[2]=m[2].1p(/\\\\/g,"");L f=d[d.M-1];7(m[1]=="#"&&f&&f.5N&&!E.3W(f)){L q=f.5N(m[2]);7((E.14.1d||E.14.2B)&&q&&1v q.2s=="25"&&q.2s!=m[2])q=E(\'[@2s="\'+m[2]+\'"]\',f)[0];d=r=q&&(!m[3]||E.12(q,m[3]))?[q]:[]}N{P(L i=0;d[i];i++){L a=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];7(a=="*"&&d[i].12.2w()=="4D")a="3v";r=E.34(r,d[i].3V(a))}7(m[1]==".")r=E.58(r,m[2]);7(m[1]=="#"){L e=[];P(L i=0;r[i];i++)7(r[i].4z("2s")==m[2]){e=[r[i]];1T}r=e}d=r}t=t.1p(k,"")}}7(t){L b=E.1F(t,r);d=r=b.r;t=E.3f(b.t)}}7(t)d=[];7(d&&p==d[0])d.4k();2j=E.34(2j,d);K 2j},58:J(r,m,a){m=" "+m+" ";L c=[];P(L i=0;r[i];i++){L b=(" "+r[i].1w+" ").1g(m)>=0;7(!a&&b||a&&!b)c.1h(r[i])}K c},1F:J(t,r,h){L d;2e(t&&t!=d){d=t;L p=E.6j,m;P(L i=0;p[i];i++){m=p[i].39(t);7(m){t=t.7V(m[0].M);m[2]=m[2].1p(/\\\\/g,"");1T}}7(!m)1T;7(m[1]==":"&&m[2]=="4I")r=G.17(m[3])?E.1F(m[3],r,R).r:E(r).4I(m[3]);N 7(m[1]==".")r=E.58(r,m[2],h);N 7(m[1]=="["){L g=[],U=m[3];P(L i=0,3g=r.M;i<3g;i++){L a=r[i],z=a[E.3S[m[2]]||m[2]];7(z==W||/6T|3R|2p/.17(m[2]))z=E.1K(a,m[2])||\'\';7((U==""&&!!z||U=="="&&z==m[5]||U=="!="&&z!=m[5]||U=="^="&&z&&!z.1g(m[5])||U=="$="&&z.6i(z.M-m[5].M)==m[5]||(U=="*="||U=="~=")&&z.1g(m[5])>=0)^h)g.1h(a)}r=g}N 7(m[1]==":"&&m[2]=="31-4m"){L e={},g=[],17=/(-?)(\\d*)n((?:\\+|-)?\\d*)/.39(m[3]=="6r"&&"2n"||m[3]=="6p"&&"2n+1"||!/\\D/.17(m[3])&&"7U+"+m[3]||m[3]),3j=(17[1]+(17[2]||1))-0,d=17[3]-0;P(L i=0,3g=r.M;i<3g;i++){L j=r[i],1b=j.1b,2s=E.Q(1b);7(!e[2s]){L c=1;P(L n=1b.1B;n;n=n.2J)7(n.15==1)n.4p=c++;e[2s]=R}L b=S;7(3j==0){7(j.4p==d)b=R}N 7((j.4p-d)%3j==0&&(j.4p-d)/3j>=0)b=R;7(b^h)g.1h(j)}r=g}N{L f=E.5d[m[1]];7(1v f!="25")f=E.5d[m[1]][m[2]];f=4A("S||J(a,i){K "+f+"}");r=E.3x(r,f,h)}}K{r:r,t:t}},4w:J(b,c){L d=[];L a=b[c];2e(a&&a!=T){7(a.15==1)d.1h(a);a=a[c]}K d},31:J(a,e,c,b){e=e||1;L d=0;P(;a;a=a[c])7(a.15==1&&++d==e)1T;K a},5m:J(n,a){L r=[];P(;n;n=n.2J){7(n.15==1&&(!a||n!=a))r.1h(n)}K r}});E.16={1c:J(f,i,g,e){7(f.15==3||f.15==8)K;7(E.14.1d&&f.54!=10)f=1e;7(!g.2A)g.2A=6.2A++;7(e!=10){L h=g;g=J(){K h.1j(6,1a)};g.Q=e;g.2A=h.2A}L j=E.Q(f,"2N")||E.Q(f,"2N",{}),1x=E.Q(f,"1x")||E.Q(f,"1x",J(){L a;7(1v E=="10"||E.16.52)K a;a=E.16.1x.1j(1a.3G.O,1a);K a});1x.O=f;E.V(i.2d(/\\s+/),J(c,b){L a=b.2d(".");b=a[0];g.U=a[1];L d=j[b];7(!d){d=j[b]={};7(!E.16.2l[b]||E.16.2l[b].4i.1O(f)===S){7(f.3F)f.3F(b,1x,S);N 7(f.6h)f.6h("4h"+b,1x)}}d[g.2A]=g;E.16.2g[b]=R});f=W},2A:1,2g:{},1Y:J(e,h,f){7(e.15==3||e.15==8)K;L i=E.Q(e,"2N"),2f,5E;7(i){7(h==10)P(L g 1r i)6.1Y(e,g);N{7(h.U){f=h.2k;h=h.U}E.V(h.2d(/\\s+/),J(b,a){L c=a.2d(".");a=c[0];7(i[a]){7(f)2T i[a][f.2A];N P(f 1r i[a])7(!c[1]||i[a][f].U==c[1])2T i[a][f];P(2f 1r i[a])1T;7(!2f){7(!E.16.2l[a]||E.16.2l[a].4g.1O(e)===S){7(e.6f)e.6f(a,E.Q(e,"1x"),S);N 7(e.6d)e.6d("4h"+a,E.Q(e,"1x"))}2f=W;2T i[a]}}})}P(2f 1r i)1T;7(!2f){L d=E.Q(e,"1x");7(d)d.O=W;E.3H(e,"2N");E.3H(e,"1x")}}},1U:J(f,b,c,d,g){b=E.2H(b||[]);7(!c){7(6.2g[f])E("*").1c([1e,T]).1U(f,b)}N{7(c.15==3||c.15==8)K 10;L a,2f,1i=E.1q(c[f]||W),16=!b[0]||!b[0].32;7(16)b.4U(6.51({U:f,2K:c}));b[0].U=f;7(E.1q(E.Q(c,"1x")))a=E.Q(c,"1x").1j(c,b);7(!1i&&c["4h"+f]&&c["4h"+f].1j(c,b)===S)a=S;7(16)b.4k();7(g&&E.1q(g)){2f=g.1j(c,a==W?b:b.6Q(a));7(2f!==10)a=2f}7(1i&&d!==S&&a!==S&&!(E.12(c,\'a\')&&f=="50")){6.52=R;1R{c[f]()}1W(e){}}6.52=S}K a},1x:J(c){L a;c=E.16.51(c||1e.16||{});L b=c.U.2d(".");c.U=b[0];L f=E.Q(6,"2N")&&E.Q(6,"2N")[c.U],3B=1N.2m.2V.1O(1a,1);3B.4U(c);P(L j 1r f){L d=f[j];3B[0].2k=d;3B[0].Q=d.Q;7(!b[1]||d.U==b[1]){L e=d.1j(6,3B);7(a!==S)a=e;7(e===S){c.32();c.41()}}}7(E.14.1d)c.2K=c.32=c.41=c.2k=c.Q=W;K a},51:J(c){L a=c;c=E.1s({},a);c.32=J(){7(a.32)a.32();a.7T=S};c.41=J(){7(a.41)a.41();a.7S=R};7(!c.2K)c.2K=c.7R||T;7(c.2K.15==3)c.2K=a.2K.1b;7(!c.4W&&c.4V)c.4W=c.4V==c.2K?c.7Q:c.4V;7(c.6b==W&&c.6a!=W){L b=T.1I,1k=T.1k;c.6b=c.6a+(b&&b.2i||1k&&1k.2i||0)-(b.68||0);c.7O=c.7N+(b&&b.2x||1k&&1k.2x||0)-(b.67||0)}7(!c.3r&&((c.4f||c.4f===0)?c.4f:c.66))c.3r=c.4f||c.66;7(!c.65&&c.64)c.65=c.64;7(!c.3r&&c.2G)c.3r=(c.2G&1?1:(c.2G&2?3:(c.2G&4?2:0)));K c},2l:{21:{4i:J(){5A();K},4g:J(){K}},47:{4i:J(){7(E.14.1d)K S;E(6).2z("4Q",E.16.2l.47.2k);K R},4g:J(){7(E.14.1d)K S;E(6).42("4Q",E.16.2l.47.2k);K R},2k:J(a){7(I(a,6))K R;1a[0].U="47";K E.16.1x.1j(6,1a)}},46:{4i:J(){7(E.14.1d)K S;E(6).2z("4P",E.16.2l.46.2k);K R},4g:J(){7(E.14.1d)K S;E(6).42("4P",E.16.2l.46.2k);K R},2k:J(a){7(I(a,6))K R;1a[0].U="46";K E.16.1x.1j(6,1a)}}}};E.1i.1s({2z:J(c,a,b){K c=="4O"?6.30(c,a,b):6.V(J(){E.16.1c(6,c,b||a,b&&a)})},30:J(d,b,c){K 6.V(J(){E.16.1c(6,d,J(a){E(6).42(a);K(c||b).1j(6,1a)},c&&b)})},42:J(a,b){K 6.V(J(){E.16.1Y(6,a,b)})},1U:J(c,a,b){K 6.V(J(){E.16.1U(c,a,6,R,b)})},63:J(c,a,b){7(6[0])K E.16.1U(c,a,6[0],S,b);K 10},2h:J(){L b=1a;K 6.50(J(a){6.4N=0==6.4N?1:0;a.32();K b[6.4N].1j(6,1a)||S})},7F:J(a,b){K 6.2z(\'47\',a).2z(\'46\',b)},21:J(a){5A();7(E.2Q)a.1O(T,E);N E.3w.1h(J(){K a.1O(6,E)});K 6}});E.1s({2Q:S,3w:[],21:J(){7(!E.2Q){E.2Q=R;7(E.3w){E.V(E.3w,J(){6.1j(T)});E.3w=W}E(T).63("21")}}});L x=S;J 5A(){7(x)K;x=R;7(T.3F&&!E.14.2B)T.3F("61",E.21,S);7(E.14.1d&&1e==3b)(J(){7(E.2Q)K;1R{T.1I.7D("2c")}1W(3e){3z(1a.3G,0);K}E.21()})();7(E.14.2B)T.3F("61",J(){7(E.2Q)K;P(L i=0;i<T.4M.M;i++)7(T.4M[i].2W){3z(1a.3G,0);K}E.21()},S);7(E.14.26){L a;(J(){7(E.2Q)K;7(T.3c!="60"&&T.3c!="1z"){3z(1a.3G,0);K}7(a===10)a=E("Y, 5O[7B=7A]").M;7(T.4M.M!=a){3z(1a.3G,0);K}E.21()})()}E.16.1c(1e,"43",E.21)}E.V(("7z,7y,43,7x,5g,4O,50,7w,"+"7v,7u,7C,4Q,4P,7t,2y,"+"59,7s,7r,7G,3e").2d(","),J(i,b){E.1i[b]=J(a){K a?6.2z(b,a):6.1U(b)}});L I=J(a,c){L b=a.4W;2e(b&&b!=c)1R{b=b.1b}1W(3e){b=c}K b==c};E(1e).2z("4O",J(){E("*").1c(T).42()});E.1i.1s({43:J(g,d,c){7(E.1q(g))K 6.2z("43",g);L e=g.1g(" ");7(e>=0){L i=g.2V(e,g.M);g=g.2V(0,e)}c=c||J(){};L f="4J";7(d)7(E.1q(d)){c=d;d=W}N{d=E.3v(d);f="5Z"}L h=6;E.3Q({1f:g,U:f,1G:"3q",Q:d,1z:J(a,b){7(b=="1X"||b=="5Y")h.3q(i?E("<1u/>").3t(a.4e.1p(/<1o(.|\\s)*?\\/1o>/g,"")).2r(i):a.4e);h.V(c,[a.4e,b,a])}});K 6},7q:J(){K E.3v(6.5X())},5X:J(){K 6.2a(J(){K E.12(6,"3i")?E.2H(6.7p):6}).1F(J(){K 6.37&&!6.2W&&(6.3o||/2y|6l/i.17(6.12)||/1t|23|3J/i.17(6.U))}).2a(J(i,c){L b=E(6).5P();K b==W?W:b.1n==1N?E.2a(b,J(a,i){K{37:c.37,1C:a}}):{37:c.37,1C:b}}).22()}});E.V("5W,5V,5U,69,5T,5S".2d(","),J(i,o){E.1i[o]=J(f){K 6.2z(o,f)}});L B=(1D 3O).3N();E.1s({22:J(d,b,a,c){7(E.1q(b)){a=b;b=W}K E.3Q({U:"4J",1f:d,Q:b,1X:a,1G:c})},7o:J(b,a){K E.22(b,W,a,"1o")},7n:J(c,b,a){K E.22(c,b,a,"2O")},7m:J(d,b,a,c){7(E.1q(b)){a=b;b={}}K E.3Q({U:"5Z",1f:d,Q:b,1X:a,1G:c})},7Z:J(a){E.1s(E.4H,a)},4H:{2g:R,U:"4J",2U:0,5R:"49/x-7j-3i-7i",6x:R,3l:R,Q:W,6t:W,3J:W,4n:{3L:"49/3L, 1t/3L",3q:"1t/3q",1o:"1t/4l, 49/4l",2O:"49/2O, 1t/4l",1t:"1t/7e",4o:"*/*"}},4q:{},3Q:J(s){L f,2Y=/=\\?(&|$)/g,1A,Q;s=E.1s(R,s,E.1s(R,{},E.4H,s));7(s.Q&&s.6x&&1v s.Q!="25")s.Q=E.3v(s.Q);7(s.1G=="4u"){7(s.U.2w()=="22"){7(!s.1f.1E(2Y))s.1f+=(s.1f.1E(/\\?/)?"&":"?")+(s.4u||"7d")+"=?"}N 7(!s.Q||!s.Q.1E(2Y))s.Q=(s.Q?s.Q+"&":"")+(s.4u||"7d")+"=?";s.1G="2O"}7(s.1G=="2O"&&(s.Q&&s.Q.1E(2Y)||s.1f.1E(2Y))){f="4u"+B++;7(s.Q)s.Q=(s.Q+"").1p(2Y,"="+f+"$1");s.1f=s.1f.1p(2Y,"="+f+"$1");s.1G="1o";1e[f]=J(a){Q=a;1X();1z();1e[f]=10;1R{2T 1e[f]}1W(e){}7(h)h.2X(g)}}7(s.1G=="1o"&&s.1Q==W)s.1Q=S;7(s.1Q===S&&s.U.2w()=="22"){L i=(1D 3O()).3N();L j=s.1f.1p(/(\\?|&)4s=.*?(&|$)/,"$a2="+i+"$2");s.1f=j+((j==s.1f)?(s.1f.1E(/\\?/)?"&":"?")+"4s="+i:"")}7(s.Q&&s.U.2w()=="22"){s.1f+=(s.1f.1E(/\\?/)?"&":"?")+s.Q;s.Q=W}7(s.2g&&!E.5M++)E.16.1U("5W");7((!s.1f.1g("9Z")||!s.1f.1g("//"))&&(s.1G=="1o"||s.1G=="2O")&&s.U.2w()=="22"){L h=T.3V("6k")[0];L g=T.2R("1o");g.3R=s.1f;7(s.7c)g.9X=s.7c;7(!f){L l=S;g.9V=g.9U=J(){7(!l&&(!6.3c||6.3c=="60"||6.3c=="1z")){l=R;1X();1z();h.2X(g)}}}h.3k(g);K 10}L m=S;L k=1e.7a?1D 7a("9S.9Q"):1D 79();k.9P(s.U,s.1f,s.3l,s.6t,s.3J);1R{7(s.Q)k.4G("9N-9M",s.5R);7(s.5I)k.4G("9L-5H-9J",E.4q[s.1f]||"9H, 9G 9E 9B 5G:5G:5G 9z");k.4G("X-9x-9u","79");k.4G("9t",s.1G&&s.4n[s.1G]?s.4n[s.1G]+", */*":s.4n.4o)}1W(e){}7(s.75)s.75(k);7(s.2g)E.16.1U("5S",[k,s]);L c=J(a){7(!m&&k&&(k.3c==4||a=="2U")){m=R;7(d){74(d);d=W}1A=a=="2U"&&"2U"||!E.73(k)&&"3e"||s.5I&&E.72(k,s.1f)&&"5Y"||"1X";7(1A=="1X"){1R{Q=E.71(k,s.1G)}1W(e){1A="5C"}}7(1A=="1X"){L b;1R{b=k.5B("70-5H")}1W(e){}7(s.5I&&b)E.4q[s.1f]=b;7(!f)1X()}N E.5t(s,k,1A);1z();7(s.3l)k=W}};7(s.3l){L d=54(c,13);7(s.2U>0)3z(J(){7(k){k.9m();7(!m)c("2U")}},s.2U)}1R{k.9l(s.Q)}1W(e){E.5t(s,k,W,e)}7(!s.3l)c();J 1X(){7(s.1X)s.1X(Q,1A);7(s.2g)E.16.1U("5T",[k,s])}J 1z(){7(s.1z)s.1z(k,1A);7(s.2g)E.16.1U("5U",[k,s]);7(s.2g&&!--E.5M)E.16.1U("5V")}K k},5t:J(s,a,b,e){7(s.3e)s.3e(a,b,e);7(s.2g)E.16.1U("69",[a,s,e])},5M:0,73:J(r){1R{K!r.1A&&9k.9j=="5b:"||(r.1A>=6Y&&r.1A<9h)||r.1A==6X||r.1A==9e||E.14.26&&r.1A==10}1W(e){}K S},72:J(a,c){1R{L b=a.5B("70-5H");K a.1A==6X||b==E.4q[c]||E.14.26&&a.1A==10}1W(e){}K S},71:J(r,b){L c=r.5B("9d-U");L d=b=="3L"||!b&&c&&c.1g("3L")>=0;L a=d?r.9c:r.4e;7(d&&a.1I.28=="5C")6Z"5C";7(b=="1o")E.5l(a);7(b=="2O")a=4A("("+a+")");K a},3v:J(a){L s=[];7(a.1n==1N||a.5j)E.V(a,J(){s.1h(3s(6.37)+"="+3s(6.1C))});N P(L j 1r a)7(a[j]&&a[j].1n==1N)E.V(a[j],J(){s.1h(3s(j)+"="+3s(6))});N s.1h(3s(j)+"="+3s(a[j]));K s.6g("&").1p(/%20/g,"+")}});E.1i.1s({1J:J(c,b){K c?6.27({1P:"1J",29:"1J",1y:"1J"},c,b):6.1F(":23").V(J(){6.Y.18=6.5x||"";7(E.1m(6,"18")=="2D"){L a=E("<"+6.28+" />").6B("1k");6.Y.18=a.1m("18");7(6.Y.18=="2D")6.Y.18="3u";a.1Y()}}).3h()},1H:J(b,a){K b?6.27({1P:"1H",29:"1H",1y:"1H"},b,a):6.1F(":4b").V(J(){6.5x=6.5x||E.1m(6,"18");6.Y.18="2D"}).3h()},6U:E.1i.2h,2h:J(a,b){K E.1q(a)&&E.1q(b)?6.6U(a,b):a?6.27({1P:"2h",29:"2h",1y:"2h"},a,b):6.V(J(){E(6)[E(6).3K(":23")?"1J":"1H"]()})},98:J(b,a){K 6.27({1P:"1J"},b,a)},97:J(b,a){K 6.27({1P:"1H"},b,a)},96:J(b,a){K 6.27({1P:"2h"},b,a)},95:J(b,a){K 6.27({1y:"1J"},b,a)},94:J(b,a){K 6.27({1y:"1H"},b,a)},9f:J(c,a,b){K 6.27({1y:a},c,b)},27:J(l,k,j,h){L i=E.6V(k,j,h);K 6[i.2S===S?"V":"2S"](J(){7(6.15!=1)K S;L g=E.1s({},i);L f=E(6).3K(":23"),4y=6;P(L p 1r l){7(l[p]=="1H"&&f||l[p]=="1J"&&!f)K E.1q(g.1z)&&g.1z.1j(6);7(p=="1P"||p=="29"){g.18=E.1m(6,"18");g.36=6.Y.36}}7(g.36!=W)6.Y.36="23";g.40=E.1s({},l);E.V(l,J(c,a){L e=1D E.2v(4y,g,c);7(/2h|1J|1H/.17(a))e[a=="2h"?f?"1J":"1H":a](l);N{L b=a.3D().1E(/^([+-]=)?([\\d+-.]+)(.*)$/),24=e.2o(R)||0;7(b){L d=2M(b[2]),2C=b[3]||"2P";7(2C!="2P"){4y.Y[c]=(d||1)+2C;24=((d||1)/e.2o(R))*24;4y.Y[c]=24+2C}7(b[1])d=((b[1]=="-="?-1:1)*d)+24;e.3Z(24,d,2C)}N e.3Z(24,a,"")}});K R})},2S:J(a,b){7(E.1q(a)||(a&&a.1n==1N)){b=a;a="2v"}7(!a||(1v a=="25"&&!b))K A(6[0],a);K 6.V(J(){7(b.1n==1N)A(6,a,b);N{A(6,a).1h(b);7(A(6,a).M==1)b.1j(6)}})},8Z:J(b,c){L a=E.3I;7(b)6.2S([]);6.V(J(){P(L i=a.M-1;i>=0;i--)7(a[i].O==6){7(c)a[i](R);a.6R(i,1)}});7(!c)6.5z();K 6}});L A=J(b,c,a){7(!b)K 10;c=c||"2v";L q=E.Q(b,c+"2S");7(!q||a)q=E.Q(b,c+"2S",a?E.2H(a):[]);K q};E.1i.5z=J(a){a=a||"2v";K 6.V(J(){L q=A(6,a);q.4k();7(q.M)q[0].1j(6)})};E.1s({6V:J(b,a,c){L d=b&&b.1n==8Y?b:{1z:c||!c&&a||E.1q(b)&&b,2t:b,3Y:c&&a||a&&a.1n!=8W&&a};d.2t=(d.2t&&d.2t.1n==53?d.2t:{9w:8U,8T:6Y}[d.2t])||8S;d.5o=d.1z;d.1z=J(){7(d.2S!==S)E(6).5z();7(E.1q(d.5o))d.5o.1j(6)};K d},3Y:{6O:J(p,n,b,a){K b+a*p},5F:J(p,n,b,a){K((-1Z.9C(p*1Z.9D)/2)+0.5)*a+b}},3I:[],3T:W,2v:J(b,c,a){6.11=c;6.O=b;6.1l=a;7(!c.3U)c.3U={}}});E.2v.2m={4C:J(){7(6.11.33)6.11.33.1j(6.O,[6.2I,6]);(E.2v.33[6.1l]||E.2v.33.4o)(6);7(6.1l=="1P"||6.1l=="29")6.O.Y.18="3u"},2o:J(a){7(6.O[6.1l]!=W&&6.O.Y[6.1l]==W)K 6.O[6.1l];L r=2M(E.1m(6.O,6.1l,a));K r&&r>-8N?r:2M(E.2q(6.O,6.1l))||0},3Z:J(c,b,d){6.5s=(1D 3O()).3N();6.24=c;6.3h=b;6.2C=d||6.2C||"2P";6.2I=6.24;6.4E=6.4F=0;6.4C();L e=6;J t(a){K e.33(a)}t.O=6.O;E.3I.1h(t);7(E.3T==W){E.3T=54(J(){L a=E.3I;P(L i=0;i<a.M;i++)7(!a[i]())a.6R(i--,1);7(!a.M){74(E.3T);E.3T=W}},13)}},1J:J(){6.11.3U[6.1l]=E.1K(6.O.Y,6.1l);6.11.1J=R;6.3Z(0,6.2o());7(6.1l=="29"||6.1l=="1P")6.O.Y[6.1l]="8L";E(6.O).1J()},1H:J(){6.11.3U[6.1l]=E.1K(6.O.Y,6.1l);6.11.1H=R;6.3Z(6.2o(),0)},33:J(a){L t=(1D 3O()).3N();7(a||t>6.11.2t+6.5s){6.2I=6.3h;6.4E=6.4F=1;6.4C();6.11.40[6.1l]=R;L b=R;P(L i 1r 6.11.40)7(6.11.40[i]!==R)b=S;7(b){7(6.11.18!=W){6.O.Y.36=6.11.36;6.O.Y.18=6.11.18;7(E.1m(6.O,"18")=="2D")6.O.Y.18="3u"}7(6.11.1H)6.O.Y.18="2D";7(6.11.1H||6.11.1J)P(L p 1r 6.11.40)E.1K(6.O.Y,p,6.11.3U[p])}7(b&&E.1q(6.11.1z))6.11.1z.1j(6.O);K S}N{L n=t-6.5s;6.4F=n/6.11.2t;6.4E=E.3Y[6.11.3Y||(E.3Y.5F?"5F":"6O")](6.4F,n,0,1,6.11.2t);6.2I=6.24+((6.3h-6.24)*6.4E);6.4C()}K R}};E.2v.33={2i:J(a){a.O.2i=a.2I},2x:J(a){a.O.2x=a.2I},1y:J(a){E.1K(a.O.Y,"1y",a.2I)},4o:J(a){a.O.Y[a.1l]=a.2I+a.2C}};E.1i.5f=J(){L b=0,3b=0,O=6[0],5q;7(O)8K(E.14){L d=O.1b,45=O,1M=O.1M,1L=O.2u,5p=26&&4t(5n)<8H,2Z=E.1m(O,"3C")=="2Z";7(O.7b){L c=O.7b();1c(c.2c+1Z.2b(1L.1I.2i,1L.1k.2i),c.3b+1Z.2b(1L.1I.2x,1L.1k.2x));1c(-1L.1I.68,-1L.1I.67)}N{1c(O.5k,O.5K);2e(1M){1c(1M.5k,1M.5K);7(3X&&!/^t(8F|d|h)$/i.17(1M.28)||26&&!5p)3a(1M);7(!2Z&&E.1m(1M,"3C")=="2Z")2Z=R;45=/^1k$/i.17(1M.28)?45:1M;1M=1M.1M}2e(d&&d.28&&!/^1k|3q$/i.17(d.28)){7(!/^a0|1V.*$/i.17(E.1m(d,"18")))1c(-d.2i,-d.2x);7(3X&&E.1m(d,"36")!="4b")3a(d);d=d.1b}7((5p&&(2Z||E.1m(45,"3C")=="4Z"))||(3X&&E.1m(45,"3C")!="4Z"))1c(-1L.1k.5k,-1L.1k.5K);7(2Z)1c(1Z.2b(1L.1I.2i,1L.1k.2i),1Z.2b(1L.1I.2x,1L.1k.2x))}5q={3b:3b,2c:b}}J 3a(a){1c(E.2q(a,"a1",R),E.2q(a,"8D",R))}J 1c(l,t){b+=4t(l)||0;3b+=4t(t)||0}K 5q}})();',62,624,'||||||this|if||||||||||||||||||||||||||||||||||||||function|return|var|length|else|elem|for|data|true|false|document|type|each|null||style||undefined|options|nodeName||browser|nodeType|event|test|display|jQuery|arguments|parentNode|add|msie|window|url|indexOf|push|fn|apply|body|prop|css|constructor|script|replace|isFunction|in|extend|text|div|typeof|className|handle|opacity|complete|status|firstChild|value|new|match|filter|dataType|hide|documentElement|show|attr|doc|offsetParent|Array|call|height|cache|try|tbody|break|trigger|table|catch|success|remove|Math||ready|get|hidden|start|string|safari|animate|tagName|width|map|max|left|split|while|ret|global|toggle|scrollLeft|done|handler|special|prototype||cur|selected|curCSS|find|id|duration|ownerDocument|fx|toLowerCase|scrollTop|select|bind|guid|opera|unit|none|pushStack|toUpperCase|button|makeArray|now|nextSibling|target|stack|parseFloat|events|json|px|isReady|createElement|queue|delete|timeout|slice|disabled|removeChild|jsre|fixed|one|nth|preventDefault|step|merge|inArray|overflow|name|innerHTML|exec|border|top|readyState|multiFilter|error|trim|rl|end|form|first|appendChild|async|elems|insertBefore|checked|childNodes|html|which|encodeURIComponent|append|block|param|readyList|grep|color|setTimeout|runtimeStyle|args|position|toString|has|addEventListener|callee|removeData|timers|password|is|xml|last|getTime|Date|domManip|ajax|src|props|timerId|orig|getElementsByTagName|isXMLDoc|mozilla|easing|custom|curAnim|stopPropagation|unbind|load|selectedIndex|offsetChild|mouseleave|mouseenter|input|application|defaultView|visible|float|String|responseText|charCode|teardown|on|setup|currentStyle|shift|javascript|child|accepts|_default|nodeIndex|lastModified|RegExp|_|parseInt|jsonp|previousSibling|dir|tr|self|getAttribute|eval|empty|update|object|pos|state|setRequestHeader|ajaxSettings|not|GET|getPropertyValue|getComputedStyle|styleSheets|lastToggle|unload|mouseout|mouseover|andSelf|getWH|container2|unshift|fromElement|relatedTarget|visibility|init|absolute|click|fix|triggered|Number|setInterval|removeAttribute|prevObject|unique|classFilter|submit|after|file|clean|expr|windowData|offset|scroll|client|deep|jquery|offsetLeft|globalEval|sibling|version|old|safari2|results|wrapAll|startTime|handleError|container|createTextNode|radio|oldblock|checkbox|dequeue|bindReady|getResponseHeader|parsererror|lastChild|index|swing|00|Modified|ifModified|clone|offsetTop|values|active|getElementById|link|val|col|contentType|ajaxSend|ajaxSuccess|ajaxComplete|ajaxStop|ajaxStart|serializeArray|notmodified|POST|loaded|DOMContentLoaded|Width|triggerHandler|ctrlKey|metaKey|keyCode|clientTop|clientLeft|ajaxError|clientX|pageX|cloneNode|detachEvent|swap|removeEventListener|join|attachEvent|substr|parse|head|textarea|reset|image|before|odd|zoom|even|prepend|username|quickClass|quickID|quickChild|processData|uuid|continue|textContent|appendTo|contents|evalScript|parent|defaultValue|setArray|CSS1Compat|compatMode|cssFloat|styleFloat|webkit|nodeValue|eq|linear|replaceWith|concat|splice|100|href|_toggle|speed|alpha|304|200|throw|Last|httpData|httpNotModified|httpSuccess|clearInterval|beforeSend|colgroup|fieldset|multiple|XMLHttpRequest|ActiveXObject|getBoundingClientRect|scriptCharset|callback|plain|img|hasClass|br|urlencoded|www|abbr|pixelLeft|post|getJSON|getScript|elements|serialize|keypress|keydown|change|mouseup|mousedown|dblclick|resize|focus|blur|stylesheet|rel|mousemove|doScroll|round|hover|keyup|padding|offsetHeight|offsetWidth|Bottom|Top|Right|clientY|pageY|Left|toElement|srcElement|cancelBubble|returnValue|0n|substring|animated|header|enabled|ajaxSetup|innerText|noConflict|size|contains|only|line|gt|weight|lt|font|uFFFF|u0128|417|inner|Height|Boolean|toggleClass|removeClass|addClass|removeAttr|replaceAll|insertAfter|wrap|prependTo|contentWindow|contentDocument|iframe|children|siblings|wrapInner|prevAll|nextAll|prev|next|parents|maxLength|maxlength|readOnly|readonly|borderTopWidth|class|able|htmlFor|522|reverse|boxModel|with|1px|compatible|10000|ie|ra|it|rv|400|fast|600|userAgent|Function|navigator|Object|stop|option|array|ig|NaN|fadeOut|fadeIn|slideToggle|slideUp|slideDown|setAttribute|changed|be|responseXML|content|1223|fadeTo|can|300|property|protocol|location|send|abort|getAttributeNode|specified|method|action|cssText|attributes|Accept|With|th|slow|Requested|td|GMT|cap|1970|cos|PI|Jan|colg|01|Thu|tfoot|Since|thead|If|Type|Content|leg|open|XMLHTTP|opt|Microsoft|embed|onreadystatechange|onload|area|charset|hr|http|inline|borderLeftWidth|1_|meta'.split('|'),0,{}))
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.dimensions.pack.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.dimensions.pack.js
new file mode 100644 (file)
index 0000000..c1f65ea
--- /dev/null
@@ -0,0 +1,12 @@
+/* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * $LastChangedDate: 2007-12-20 08:43:48 -0600 (Thu, 20 Dec 2007) $
+ * $Rev: 4257 $
+ *
+ * Version: 1.2
+ *
+ * Requires: jQuery 1.2+
+ */
+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(5($){$.19={P:\'1.2\'};$.u([\'j\',\'w\'],5(i,d){$.q[\'O\'+d]=5(){p(!3[0])6;g a=d==\'j\'?\'s\':\'m\',e=d==\'j\'?\'D\':\'C\';6 3.B(\':y\')?3[0][\'L\'+d]:4(3,d.x())+4(3,\'n\'+a)+4(3,\'n\'+e)};$.q[\'I\'+d]=5(b){p(!3[0])6;g c=d==\'j\'?\'s\':\'m\',e=d==\'j\'?\'D\':\'C\';b=$.F({t:Z},b||{});g a=3.B(\':y\')?3[0][\'8\'+d]:4(3,d.x())+4(3,\'E\'+c+\'w\')+4(3,\'E\'+e+\'w\')+4(3,\'n\'+c)+4(3,\'n\'+e);6 a+(b.t?(4(3,\'t\'+c)+4(3,\'t\'+e)):0)}});$.u([\'m\',\'s\'],5(i,b){$.q[\'l\'+b]=5(a){p(!3[0])6;6 a!=W?3.u(5(){3==h||3==r?h.V(b==\'m\'?a:$(h)[\'U\'](),b==\'s\'?a:$(h)[\'T\']()):3[\'l\'+b]=a}):3[0]==h||3[0]==r?S[(b==\'m\'?\'R\':\'Q\')]||$.N&&r.M[\'l\'+b]||r.A[\'l\'+b]:3[0][\'l\'+b]}});$.q.F({z:5(){g a=0,f=0,o=3[0],8,9,7,v;p(o){7=3.7();8=3.8();9=7.8();8.f-=4(o,\'K\');8.k-=4(o,\'J\');9.f+=4(7,\'H\');9.k+=4(7,\'Y\');v={f:8.f-9.f,k:8.k-9.k}}6 v},7:5(){g a=3[0].7;G(a&&(!/^A|10$/i.16(a.15)&&$.14(a,\'z\')==\'13\'))a=a.7;6 $(a)}});5 4(a,b){6 12($.11(a.17?a[0]:a,b,18))||0}})(X);',62,72,'|||this|num|function|return|offsetParent|offset|parentOffset|||||borr|top|var|window||Height|left|scroll|Left|padding|elem|if|fn|document|Top|margin|each|results|Width|toLowerCase|visible|position|body|is|Right|Bottom|border|extend|while|borderTopWidth|outer|marginLeft|marginTop|client|documentElement|boxModel|inner|version|pageYOffset|pageXOffset|self|scrollTop|scrollLeft|scrollTo|undefined|jQuery|borderLeftWidth|false|html|curCSS|parseInt|static|css|tagName|test|jquery|true|dimensions'.split('|'),0,{}))
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.grid.columnSizing.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.grid.columnSizing.js
new file mode 100644 (file)
index 0000000..32b8d2a
--- /dev/null
@@ -0,0 +1,219 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//     Programador: Enrique Meléndez Estrada\r
+//     Fecha: 02 - Noviembre - 2006\r
+//     Version: 1.02\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+jQuery.fn.columnSizing = function(o) {\r
+               \r
+       // default parameters, properties or settings\r
+       o = jQuery.extend({\r
+               selectCells : "tr:first>*",\r
+               minWidth : 8,   //pixels minimum width;\r
+               viewResize : true,\r
+               viewGhost : true,\r
+               tableWidthFixed : false,\r
+               fadeOut : true,\r
+               opacity : 0.5,\r
+               classTable :    "jquery_columnSizing",\r
+               classHandler :  "jquery_columnSizing_handler",\r
+               classDragLine : "jquery_columnSizing_dragLine",\r
+               classDragArea : "jquery_columnSizing_dragArea",\r
+               cssHandler : {\r
+                       position: "relative",\r
+                       /*top:"2px",*/\r
+                       right:"-3px",\r
+                       float:"right",\r
+                       /*width:"0px",*/\r
+                       borderRight:"2px solid #fff",\r
+                       borderLeft:"2px solid #555",\r
+                       height:"20px",\r
+                       cursor:"col-resize"\r
+                       },\r
+               cssDragLine : {\r
+                       borderRight:"4px solid #777",\r
+                       cursor:"col-resize"\r
+                       },\r
+               cssDragArea : {\r
+                       border:"2px solid #777",\r
+                       backgroundColor:"#eee",\r
+                       cursor:"col-resize"\r
+                       },\r
+               title : 'Expand/Collapse this column',\r
+               speed : true, /* loading fast or compatibility... */\r
+               cookies : false,\r
+               dtop: -2,\r
+               dleft: -4,\r
+               loadingTime : 0,\r
+               onLoad : null\r
+       }, o || {});\r
+       \r
+       o.cookies = o.cookies && !!jQuery.cookie; /** if exists plugin 'jquery.cookies.js' **/\r
+\r
+       if (o.viewGhost){\r
+               var $Div = jQuery('<div style="display:none;position:absolute;top:0;left:0;height:0;width:0;"></div>')\r
+                               .appendTo('body')\r
+                               .css(o.cssDragArea)\r
+                               .addClass(o.classDragArea)\r
+                               .css('opacity',o.opacity);\r
+               var sDiv = $Div.get(0).style;\r
+       }\r
+                       \r
+       return this.each(function(index){\r
+               o.loadingTime = new Date().getTime();\r
+               \r
+               /* load table cookie and init its width */\r
+               if (o.cookies) {\r
+                       var cookieTableName = document.location.href+"_"+index;\r
+                       var cookieTableValue= jQuery.cookie(cookieTableName);\r
+                       if (cookieTableValue != null)\r
+                               this.style.width = cookieTableValue+"px";\r
+                       }\r
+               /** CSS SPECIAL FOR TABLES**/\r
+               jQuery(this)\r
+                       .addClass(o.classTable)\r
+                       //.find('td').css({ overflow : 'hidden' })\r
+                       ;        \r
+               \r
+               /* variables globales */\r
+               var oTable = this;\r
+               var wTable = (o.speed) ? oTable.clientWidth : jQuery(this).width();\r
+               var hTable = (o.speed) ? oTable.clientHeight : jQuery(this).height();\r
+\r
+               jQuery(o.selectCells,this)\r
+                       .each(function(index){\r
+                               jQuery('<div class="'+o.classHandler+'" title="'+ o.title+'"></div>')\r
+                                       .css(o.cssHandler)\r
+                                       /*.css('left',this.offsetLeft+this.offsetWidth+"px")*/\r
+                                       .prependTo(this)\r
+                                       .each(function(){\r
+                                               this.dx = 0;\r
+                                               this.ancho = 0;\r
+                                               this.umbral = false;\r
+                                               this.$td = jQuery(this).parents('td,th').eq(0);\r
+                                               this.otd = this.$td.get(0);\r
+                                               this.sDragHelper = null;\r
+                                               \r
+                                               /* loading fast or compatibility... */\r
+                                               this.wtd = (o.speed) ? null : this.$td.width(); \r
+                                               this.wtd0 = this.wtd;\r
+                                               \r
+                                               /* load column cookie and init its width */\r
+                                               if (o.cookies){\r
+                                                       this.cookieColName = cookieTableName+'_'+index;\r
+                                                       this.cookieColName0 = this.cookieColName+'0';\r
+                                                       this.cookieColValue = jQuery.cookie(this.cookieColName);\r
+                                                       this.cookieColValue0 = jQuery.cookie(this.cookieColName0);\r
+                                                       if (this.cookieColValue != null){\r
+                                                               this.otd.style.width = this.cookieColValue+"px";\r
+                                                               this.wtd = this.cookieColValue;\r
+                                                               this.wtd0= this.cookieColValue0;\r
+                                                               }\r
+                                                       }\r
+                                               })\r
+                                       .dblclick( function() { \r
+                                               /* if loading fast, only once... */\r
+                                               if (this.wtd == null){          \r
+                                                               this.wtd =              this.otd.offsetWidth; \r
+                                                               this.wtd0=              this.wtd;\r
+                                                               }\r
+                                               \r
+                                               /* change column width */\r
+                                               var minimized = this.wtd == o.minWidth;\r
+                                               this.wtd = (minimized) ? this.wtd0 : o.minWidth;\r
+                                               this.otd.style.width = this.wtd + "px";\r
+\r
+                                               /* change table width (if not fixed) */\r
+                                               if(!o.tableWidthFixed){\r
+                                                       var d = this.wtd0-o.minWidth;\r
+                                                       wTable = wTable+((minimized)?d:-d);\r
+                                                       oTable.style.width = wTable+"px";\r
+                                                       }\r
+                                               \r
+                                               /* save column and table cookie */\r
+                                               if (o.cookies){\r
+                                                       jQuery.cookie(this.cookieColName, this.wtd);\r
+                                                       jQuery.cookie(this.cookieColName0, this.wtd0);\r
+                                                       jQuery.cookie(cookieTableName, wTable);\r
+                                                       }\r
+                                               })\r
+                                       .Draggable({\r
+                                               axis:   'horizontally',\r
+                                               containment: 'document',\r
+                                               frameClass: o.classDragLine,\r
+                                               ghosting:       true,\r
+                                               opacity:        o.opacity,\r
+                                               revert:         true,\r
+                                               onStart: function(e){\r
+                                                       \r
+                                                       /* if loading fast, only once... */\r
+                                                       if (this.wtd == null){  \r
+                                                               this.wtd =              this.otd.offsetWidth; //this.$td.width();\r
+                                                               this.wtd0=              this.wtd;\r
+                                                               }\r
+                                                       hTable = oTable.clientHeight;\r
+                                                       if (o.viewGhost){\r
+                                                               sDiv.top =              this.dragCfg.oC.y+o.dtop+"px";\r
+                                                               sDiv.left=              this.dragCfg.currentPointer.x+o.dleft-this.wtd+"px";\r
+                                                               sDiv.height =   hTable+"px";\r
+                                                               sDiv.width =    this.wtd+"px";\r
+                                                               sDiv.display = "block";\r
+                                                               }\r
+                                                       else{\r
+                                                               if (!this.sDragHelper)\r
+                                                                       this.sDragHelper = jQuery('#dragHelper').css(o.cssDragLine).get(0).style;\r
+                                                               this.sDragHelper.height = hTable+"px";\r
+                                                               };\r
+                                                       },\r
+                                               onDrag: (o.viewResize || o.viewGhost)? function(e){\r
+                                                       this.dx = this.dragCfg.currentPointer.x-this.dragCfg.pointer.x;\r
+                                                       this.ancho = this.wtd+this.dx;\r
+                                                       this.umbral = (o.minWidth-this.ancho > 0);\r
+                                                       this.jarrr = (this.umbral)? o.minWidth: this.ancho;\r
+                                                       if (o.viewGhost) {\r
+                                                               sDiv.width = this.jarrr+"px";\r
+                                                               if (!o.viewResize) return;\r
+                                                               };\r
+                                                       this.otd.style.width = this.jarrr + "px";\r
+                                                       \r
+                                                       /* change table width (if not fixed) */\r
+                                                       if(!o.tableWidthFixed){\r
+                                                               oTable.style.width = (this.umbral)?wTable+o.minWidth-this.wtd+"px":wTable+this.dx+"px";\r
+                                                               };\r
+                                                       }: null,\r
+                                               onStop: function(e){\r
+                                                       if (!o.viewResize || o.viewGhost){\r
+                                                               this.dx = this.dragCfg.currentPointer.x-this.dragCfg.pointer.x;\r
+                                                               this.ancho = this.wtd+this.dx;\r
+                                                               this.umbral = (o.minWidth-this.ancho > 0);\r
+                                                               this.jarrr = (this.umbral) ? o.minWidth : this.ancho;\r
+                                                               this.otd.style.width = this.jarrr + "px";\r
+                                                               if (o.viewGhost)\r
+                                                                       if (o.fadeOut)  $Div.fadeOut('slow');\r
+                                                                       else                    sDiv.display = "none";\r
+                                                               };\r
+                                                       \r
+                                                       /* change table width (if not fixed) */\r
+                                                       if(!o.tableWidthFixed){\r
+                                                               wTable = (this.umbral)?wTable+o.minWidth-this.wtd:wTable+this.dx;\r
+                                                               oTable.style.width = wTable+"px";\r
+                                                               };\r
+                                                       this.wtd0 = this.wtd;\r
+                                                       this.wtd = parseInt(this.otd.style.width);\r
+                                                       this.wtd0 = (this.wtd == o.minWidth) ? this.wtd0 : this.wtd;\r
+                                                       \r
+                                                       /* save column and table cookie */\r
+                                                       if (o.cookies){\r
+                                                               jQuery.cookie(this.cookieColName, this.wtd);\r
+                                                               jQuery.cookie(this.cookieColName0, this.wtd0);\r
+                                                               jQuery.cookie(cookieTableName, wTable);\r
+                                                               }\r
+                                               }\r
+                                       })\r
+                               });\r
+                       o.loadingTime = new Date().getTime() - o.loadingTime;\r
+                       if (typeof(o.onLoad) == "function")\r
+                               o.onLoad();\r
+                       })\r
+       \r
+};\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.idrag.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.idrag.js
new file mode 100644 (file)
index 0000000..eb5184c
--- /dev/null
@@ -0,0 +1,587 @@
+/**
+ * Interface Elements for jQuery
+ * Draggable
+ *
+ * http://interface.eyecon.ro
+ *
+ * Copyright (c) 2006 Stefan Petre
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ */
+/**
+ * Create a draggable element with a number of advanced options including callback, Google Maps type draggables,
+ * reversion, ghosting, and grid dragging.
+ * 
+ * @name Draggable
+ * @descr Creates draggable elements that can be moved across the page.
+ * @param Hash hash A hash of parameters. All parameters are optional.
+ * @option String handle (optional) The jQuery selector matching the handle that starts the draggable
+ * @option DOMElement handle (optional) The DOM Element of the handle that starts the draggable
+ * @option Boolean revert (optional) When true, on stop-drag the element returns to initial position
+ * @option Boolean ghosting (optional) When true, a copy of the element is moved
+ * @option Integer zIndex (optional) zIndex depth for the element while it is being dragged
+ * @option Float opacity (optional) A number between 0 and 1 that indicates the opacity of the element while being dragged
+ * @option Integer grid (optional) (optional) A number of pixels indicating the grid that the element should snap to
+ * @option Array grid (optional) A number of x-pixels and y-pixels indicating the grid that the element should snap to
+ * @option Integer fx (optional) Duration for the effect (like ghosting or revert) applied to the draggable
+ * @option String containment (optional) Define the zone where the draggable can be moved. 'parent' moves it inside parent
+ *                           element, while 'document' prevents it from leaving the document and forcing additional
+ *                           scrolling
+ * @option Array containment An 4-element array (left, top, width, height) indicating the containment of the element
+ * @option String axis (optional) Set an axis: vertical (with 'vertically') or horizontal (with 'horizontally')
+ * @option Function onStart (optional) Callback function triggered when the dragging starts
+ * @option Function onStop (optional) Callback function triggered when the dragging stops
+ * @option Function onChange (optional) Callback function triggered when the dragging stop *and* the element was moved at least
+ *                          one pixel
+ * @option Function onDrag (optional) Callback function triggered while the element is dragged. Receives two parameters: x and y
+ *                        coordinates. You can return an object with new coordinates {x: x, y: y} so this way you can
+ *                        interact with the dragging process (for instance, build your containment)
+ * @option Boolean insideParent Forces the element to remain inside its parent when being dragged (like Google Maps)
+ * @option Integer snapDistance (optional) The element is not moved unless it is dragged more than snapDistance. You can prevent
+ *                             accidental dragging and keep regular clicking enabled (for links or form elements, 
+ *                             for instance)
+ * @option Object cursorAt (optional) The dragged element is moved to the cursor position with the offset specified. Accepts value
+ *                        for top, left, right and bottom offset. Basically, this forces the cursor to a particular
+ *                        position during the entire drag operation.
+ * @option Boolean autoSize (optional) When true, the drag helper is resized to its content, instead of the dragged element's sizes
+ * @option String frameClass (optional) When is set the cloned element is hidden so only a frame is dragged
+ * @type jQuery
+ * @cat Plugins/Interface
+ * @author Stefan Petre
+ */
+jQuery.iDrag = {
+       helper : null,
+       dragged: null,
+       destroy : function()
+       {
+               return this.each(
+                       function ()
+                       {
+                               if (this.isDraggable) {
+                                       this.dragCfg.dhe.unbind('mousedown', jQuery.iDrag.draginit);
+                                       this.dragCfg = null;
+                                       this.isDraggable = false;
+                                       if(jQuery.browser.msie) {
+                                               this.unselectable = "off";
+                                       } else {
+                                               this.style.MozUserSelect = '';
+                                               this.style.KhtmlUserSelect = '';
+                                               this.style.userSelect = '';
+                                       }
+                               }
+                       }
+               );
+       },
+       draginit : function (e)
+       {
+               if (jQuery.iDrag.dragged != null) {
+                       jQuery.iDrag.dragstop(e);
+                       return false;
+               }
+               var elm = this.dragElem;
+               jQuery(document)
+                       .bind('mousemove', jQuery.iDrag.dragmove)
+                       .bind('mouseup', jQuery.iDrag.dragstop);
+               elm.dragCfg.pointer = jQuery.iUtil.getPointer(e);
+               elm.dragCfg.currentPointer = elm.dragCfg.pointer;
+               elm.dragCfg.init = false;
+               elm.dragCfg.fromHandler = this != this.dragElem;
+               jQuery.iDrag.dragged = elm;
+               if (elm.dragCfg.si && this != this.dragElem) {
+                               parentPos = jQuery.iUtil.getPosition(elm.parentNode);
+                               sliderSize = jQuery.iUtil.getSize(elm);
+                               sliderPos = {
+                                       x : parseInt(jQuery.css(elm,'left')) || 0,
+                                       y : parseInt(jQuery.css(elm,'top')) || 0
+                               };
+                               dx = elm.dragCfg.currentPointer.x - parentPos.x - sliderSize.wb/2 - sliderPos.x;
+                               dy = elm.dragCfg.currentPointer.y - parentPos.y - sliderSize.hb/2 - sliderPos.y;
+                               jQuery.iSlider.dragmoveBy(elm, [dx, dy]);
+               }
+               return jQuery.selectKeyHelper||false;
+       },
+
+       dragstart : function(e)
+       {
+               var elm = jQuery.iDrag.dragged;
+               elm.dragCfg.init = true;
+
+               var dEs = elm.style;
+
+               elm.dragCfg.oD = jQuery.css(elm,'display');
+               elm.dragCfg.oP = jQuery.css(elm,'position');
+               if (!elm.dragCfg.initialPosition)
+                       elm.dragCfg.initialPosition = elm.dragCfg.oP;
+
+               elm.dragCfg.oR = {
+                       x : parseInt(jQuery.css(elm,'left')) || 0,
+                       y : parseInt(jQuery.css(elm,'top')) || 0
+               };
+               elm.dragCfg.diffX = 0;
+               elm.dragCfg.diffY = 0;
+               if (jQuery.browser.msie) {
+                       var oldBorder = jQuery.iUtil.getBorder(elm, true);
+                       elm.dragCfg.diffX = oldBorder.l||0;
+                       elm.dragCfg.diffY = oldBorder.t||0;
+               }
+
+               elm.dragCfg.oC = jQuery.extend(
+                       jQuery.iUtil.getPosition(elm),
+                       jQuery.iUtil.getSize(elm)
+               );
+               if (elm.dragCfg.oP != 'relative' && elm.dragCfg.oP != 'absolute') {
+                       dEs.position = 'relative';
+               }
+
+               jQuery.iDrag.helper.empty();
+               var clonedEl = elm.cloneNode(true);
+               
+               jQuery(clonedEl).css(
+                       {
+                               display:        'block',
+                               left:           '0px',
+                               top:            '0px'
+                       }
+               );
+               clonedEl.style.marginTop = '0';
+               clonedEl.style.marginRight = '0';
+               clonedEl.style.marginBottom = '0';
+               clonedEl.style.marginLeft = '0';
+               jQuery.iDrag.helper.append(clonedEl);
+               
+               var dhs = jQuery.iDrag.helper.get(0).style;
+
+               if (elm.dragCfg.autoSize) {
+                       dhs.width = 'auto';
+                       dhs.height = 'auto';
+               } else {
+                       dhs.height = elm.dragCfg.oC.hb + 'px';
+                       dhs.width = elm.dragCfg.oC.wb + 'px';
+               }
+
+               dhs.display = 'block';
+               dhs.marginTop = '0px';
+               dhs.marginRight = '0px';
+               dhs.marginBottom = '0px';
+               dhs.marginLeft = '0px';
+
+               //remeasure the clone to check if the size was changed by user's functions
+               jQuery.extend(
+                       elm.dragCfg.oC,
+                       jQuery.iUtil.getSize(clonedEl)
+               );
+
+               if (elm.dragCfg.cursorAt) {
+                       if (elm.dragCfg.cursorAt.left) {
+                               elm.dragCfg.oR.x += elm.dragCfg.pointer.x - elm.dragCfg.oC.x - elm.dragCfg.cursorAt.left;
+                               elm.dragCfg.oC.x = elm.dragCfg.pointer.x - elm.dragCfg.cursorAt.left;
+                       }
+                       if (elm.dragCfg.cursorAt.top) {
+                               elm.dragCfg.oR.y += elm.dragCfg.pointer.y - elm.dragCfg.oC.y - elm.dragCfg.cursorAt.top;
+                               elm.dragCfg.oC.y = elm.dragCfg.pointer.y - elm.dragCfg.cursorAt.top;
+                       }
+                       if (elm.dragCfg.cursorAt.right) {
+                               elm.dragCfg.oR.x += elm.dragCfg.pointer.x - elm.dragCfg.oC.x -elm.dragCfg.oC.hb + elm.dragCfg.cursorAt.right;
+                               elm.dragCfg.oC.x = elm.dragCfg.pointer.x - elm.dragCfg.oC.wb + elm.dragCfg.cursorAt.right;
+                       }
+                       if (elm.dragCfg.cursorAt.bottom) {
+                               elm.dragCfg.oR.y += elm.dragCfg.pointer.y - elm.dragCfg.oC.y - elm.dragCfg.oC.hb + elm.dragCfg.cursorAt.bottom;
+                               elm.dragCfg.oC.y = elm.dragCfg.pointer.y - elm.dragCfg.oC.hb + elm.dragCfg.cursorAt.bottom;
+                       }
+               }
+               elm.dragCfg.nx = elm.dragCfg.oR.x;
+               elm.dragCfg.ny = elm.dragCfg.oR.y;
+
+               if (elm.dragCfg.insideParent || elm.dragCfg.containment == 'parent') {
+                       parentBorders = jQuery.iUtil.getBorder(elm.parentNode, true);
+                       elm.dragCfg.oC.x = elm.offsetLeft + (jQuery.browser.msie ? 0 : jQuery.browser.opera ? -parentBorders.l : parentBorders.l);
+                       elm.dragCfg.oC.y = elm.offsetTop + (jQuery.browser.msie ? 0 : jQuery.browser.opera ? -parentBorders.t : parentBorders.t);
+                       jQuery(elm.parentNode).append(jQuery.iDrag.helper.get(0));
+               }
+               if (elm.dragCfg.containment) {
+                       jQuery.iDrag.getContainment(elm);
+                       elm.dragCfg.onDragModifier.containment = jQuery.iDrag.fitToContainer;
+               }
+
+               if (elm.dragCfg.si) {
+                       jQuery.iSlider.modifyContainer(elm);
+               }
+
+               dhs.left = elm.dragCfg.oC.x - elm.dragCfg.diffX + 'px';
+               dhs.top = elm.dragCfg.oC.y - elm.dragCfg.diffY + 'px';
+               //resize the helper to fit the clone
+               dhs.width = elm.dragCfg.oC.wb + 'px';
+               dhs.height = elm.dragCfg.oC.hb + 'px';
+
+               jQuery.iDrag.dragged.dragCfg.prot = false;
+
+               if (elm.dragCfg.gx) {
+                       elm.dragCfg.onDragModifier.grid = jQuery.iDrag.snapToGrid;
+               }
+               if (elm.dragCfg.zIndex != false) {
+                       jQuery.iDrag.helper.css('zIndex', elm.dragCfg.zIndex);
+               }
+               if (elm.dragCfg.opacity) {
+                       jQuery.iDrag.helper.css('opacity', elm.dragCfg.opacity);
+                       if (window.ActiveXObject) {
+                               jQuery.iDrag.helper.css('filter', 'alpha(opacity=' + elm.dragCfg.opacity * 100 + ')');
+                       }
+               }
+
+               if(elm.dragCfg.frameClass) {
+                       jQuery.iDrag.helper.addClass(elm.dragCfg.frameClass);
+                       jQuery.iDrag.helper.get(0).firstChild.style.display = 'none';
+               }
+               if (elm.dragCfg.onStart)
+                       elm.dragCfg.onStart.apply(elm, [clonedEl, elm.dragCfg.oR.x, elm.dragCfg.oR.y]);
+               if (jQuery.iDrop && jQuery.iDrop.count > 0 ){
+                       jQuery.iDrop.highlight(elm);
+               }
+               if (elm.dragCfg.ghosting == false) {
+                       dEs.display = 'none';
+               }
+               return false;
+       },
+
+       getContainment : function(elm)
+       {
+               if (elm.dragCfg.containment.constructor == String) {
+                       if (elm.dragCfg.containment == 'parent') {
+                               elm.dragCfg.cont = jQuery.extend(
+                                       {x:0,y:0},
+                                       jQuery.iUtil.getSize(elm.parentNode)
+                               );
+                               var contBorders = jQuery.iUtil.getBorder(elm.parentNode, true);
+                               elm.dragCfg.cont.w = elm.dragCfg.cont.wb - contBorders.l - contBorders.r;
+                               elm.dragCfg.cont.h = elm.dragCfg.cont.hb - contBorders.t - contBorders.b;
+                       } else if (elm.dragCfg.containment == 'document') {
+                               var clnt = jQuery.iUtil.getClient();
+                               elm.dragCfg.cont = {
+                                       x : 0,
+                                       y : 0,
+                                       w : clnt.w,
+                                       h : clnt.h
+                               };
+                       }
+               } else if (elm.dragCfg.containment.constructor == Array) {
+                       elm.dragCfg.cont = {
+                               x : parseInt(elm.dragCfg.containment[0])||0,
+                               y : parseInt(elm.dragCfg.containment[1])||0,
+                               w : parseInt(elm.dragCfg.containment[2])||0,
+                               h : parseInt(elm.dragCfg.containment[3])||0
+                       };
+               }
+               elm.dragCfg.cont.dx = elm.dragCfg.cont.x - elm.dragCfg.oC.x;
+               elm.dragCfg.cont.dy = elm.dragCfg.cont.y - elm.dragCfg.oC.y;
+       },
+
+       hidehelper : function(dragged)
+       {
+               if (dragged.dragCfg.insideParent || dragged.dragCfg.containment == 'parent') {
+                       jQuery('body', document).append(jQuery.iDrag.helper.get(0));
+               }
+               jQuery.iDrag.helper.empty().hide().css('opacity', 1);
+               if (window.ActiveXObject) {
+                       jQuery.iDrag.helper.css('filter', 'alpha(opacity=100)');
+               }
+       },
+
+       dragstop : function(e)
+       {
+
+               jQuery(document)
+                       .unbind('mousemove', jQuery.iDrag.dragmove)
+                       .unbind('mouseup', jQuery.iDrag.dragstop);
+
+               if (jQuery.iDrag.dragged == null) {
+                       return;
+               }
+               var dragged = jQuery.iDrag.dragged;
+
+               jQuery.iDrag.dragged = null;
+
+               if (dragged.dragCfg.init == false) {
+                       return false;
+               }
+               if (dragged.dragCfg.so == true) {
+                       jQuery(dragged).css('position', dragged.dragCfg.oP);
+               }
+               var dEs = dragged.style;
+
+               if (dragged.si) {
+                       jQuery.iDrag.helper.css('cursor', 'move');
+               }
+               if(dragged.dragCfg.frameClass) {
+                       jQuery.iDrag.helper.removeClass(dragged.dragCfg.frameClass);
+               }
+
+               if (dragged.dragCfg.revert == false) {
+                       if (dragged.dragCfg.fx > 0) {
+                               if (!dragged.dragCfg.axis || dragged.dragCfg.axis == 'horizontally') {
+                                       var x = new jQuery.fx(dragged,{duration:dragged.dragCfg.fx}, 'left');
+                                       x.custom(dragged.dragCfg.oR.x,dragged.dragCfg.nRx);
+                               }
+                               if (!dragged.dragCfg.axis || dragged.dragCfg.axis == 'vertically') {
+                                       var y = new jQuery.fx(dragged,{duration:dragged.dragCfg.fx}, 'top');
+                                       y.custom(dragged.dragCfg.oR.y,dragged.dragCfg.nRy);
+                               }
+                       } else {
+                               if (!dragged.dragCfg.axis || dragged.dragCfg.axis == 'horizontally')
+                                       dragged.style.left = dragged.dragCfg.nRx + 'px';
+                               if (!dragged.dragCfg.axis || dragged.dragCfg.axis == 'vertically')
+                                       dragged.style.top = dragged.dragCfg.nRy + 'px';
+                       }
+                       jQuery.iDrag.hidehelper(dragged);
+                       if (dragged.dragCfg.ghosting == false) {
+                               jQuery(dragged).css('display', dragged.dragCfg.oD);
+                       }
+               } else if (dragged.dragCfg.fx > 0) {
+                       dragged.dragCfg.prot = true;
+                       var dh = false;
+                       if(jQuery.iDrop && jQuery.iSort && dragged.dragCfg.so) {
+                               dh = jQuery.iUtil.getPosition(jQuery.iSort.helper.get(0));
+                       }
+                       jQuery.iDrag.helper.animate(
+                               {
+                                       left : dh ? dh.x : dragged.dragCfg.oC.x,
+                                       top : dh ? dh.y : dragged.dragCfg.oC.y
+                               },
+                               dragged.dragCfg.fx,
+                               function()
+                               {
+                                       dragged.dragCfg.prot = false;
+                                       if (dragged.dragCfg.ghosting == false) {
+                                               dragged.style.display = dragged.dragCfg.oD;
+                                       }
+                                       jQuery.iDrag.hidehelper(dragged);
+                               }
+                       );
+               } else {
+                       jQuery.iDrag.hidehelper(dragged);
+                       if (dragged.dragCfg.ghosting == false) {
+                               jQuery(dragged).css('display', dragged.dragCfg.oD);
+                       }
+               }
+
+               if (jQuery.iDrop && jQuery.iDrop.count > 0 ){
+                       jQuery.iDrop.checkdrop(dragged);
+               }
+               if (jQuery.iSort && dragged.dragCfg.so) {
+                       jQuery.iSort.check(dragged);
+               }
+               if (dragged.dragCfg.onChange && (dragged.dragCfg.nRx != dragged.dragCfg.oR.x || dragged.dragCfg.nRy != dragged.dragCfg.oR.y)){
+                       dragged.dragCfg.onChange.apply(dragged, dragged.dragCfg.lastSi||[0,0,dragged.dragCfg.nRx,dragged.dragCfg.nRy]);
+               }
+               if (dragged.dragCfg.onStop)
+                       dragged.dragCfg.onStop.apply(dragged);
+               return false;
+       },
+
+       snapToGrid : function(x, y, dx, dy)
+       {
+               if (dx != 0)
+                       dx = parseInt((dx + (this.dragCfg.gx * dx/Math.abs(dx))/2)/this.dragCfg.gx) * this.dragCfg.gx;
+               if (dy != 0)
+                       dy = parseInt((dy + (this.dragCfg.gy * dy/Math.abs(dy))/2)/this.dragCfg.gy) * this.dragCfg.gy;
+               return {
+                       dx : dx,
+                       dy : dy,
+                       x: 0,
+                       y: 0
+               };
+       },
+
+       fitToContainer : function(x, y, dx, dy)
+       {
+               dx = Math.min(
+                               Math.max(dx,this.dragCfg.cont.dx),
+                               this.dragCfg.cont.w + this.dragCfg.cont.dx - this.dragCfg.oC.wb
+                       );
+               dy = Math.min(
+                               Math.max(dy,this.dragCfg.cont.dy),
+                               this.dragCfg.cont.h + this.dragCfg.cont.dy - this.dragCfg.oC.hb
+                       );
+
+               return {
+                       dx : dx,
+                       dy : dy,
+                       x: 0,
+                       y: 0
+               }
+       },
+
+       dragmove : function(e)
+       {
+               if (jQuery.iDrag.dragged == null || jQuery.iDrag.dragged.dragCfg.prot == true) {
+                       return;
+               }
+
+               var dragged = jQuery.iDrag.dragged;
+
+               dragged.dragCfg.currentPointer = jQuery.iUtil.getPointer(e);
+               if (dragged.dragCfg.init == false) {
+                       distance = Math.sqrt(Math.pow(dragged.dragCfg.pointer.x - dragged.dragCfg.currentPointer.x, 2) + Math.pow(dragged.dragCfg.pointer.y - dragged.dragCfg.currentPointer.y, 2));
+                       if (distance < dragged.dragCfg.snapDistance){
+                               return;
+                       } else {
+                               jQuery.iDrag.dragstart(e);
+                       }
+               }
+
+               var dx = dragged.dragCfg.currentPointer.x - dragged.dragCfg.pointer.x;
+               var dy = dragged.dragCfg.currentPointer.y - dragged.dragCfg.pointer.y;
+
+               for (var i in dragged.dragCfg.onDragModifier) {
+                       var newCoords = dragged.dragCfg.onDragModifier[i].apply(dragged, [dragged.dragCfg.oR.x + dx, dragged.dragCfg.oR.y + dy, dx, dy]);
+                       if (newCoords && newCoords.constructor == Object) {
+                               dx = i != 'user' ? newCoords.dx : (newCoords.x - dragged.dragCfg.oR.x);
+                               dy = i != 'user' ? newCoords.dy : (newCoords.y - dragged.dragCfg.oR.y);
+                       }
+               }
+
+               dragged.dragCfg.nx = dragged.dragCfg.oC.x + dx - dragged.dragCfg.diffX;
+               dragged.dragCfg.ny = dragged.dragCfg.oC.y + dy - dragged.dragCfg.diffY;
+
+               if (dragged.dragCfg.si && (dragged.dragCfg.onSlide || dragged.dragCfg.onChange)) {
+                       jQuery.iSlider.onSlide(dragged, dragged.dragCfg.nx, dragged.dragCfg.ny);
+               }
+
+               if(dragged.dragCfg.onDrag)
+                       dragged.dragCfg.onDrag.apply(dragged, [dragged.dragCfg.oR.x + dx, dragged.dragCfg.oR.y + dy]);
+                       
+               if (!dragged.dragCfg.axis || dragged.dragCfg.axis == 'horizontally') {
+                       dragged.dragCfg.nRx = dragged.dragCfg.oR.x + dx;
+                       jQuery.iDrag.helper.get(0).style.left = dragged.dragCfg.nx + 'px';
+               }
+               if (!dragged.dragCfg.axis || dragged.dragCfg.axis == 'vertically') {
+                       dragged.dragCfg.nRy = dragged.dragCfg.oR.y + dy;
+                       jQuery.iDrag.helper.get(0).style.top = dragged.dragCfg.ny + 'px';
+               }
+               
+               if (jQuery.iDrop && jQuery.iDrop.count > 0 ){
+                       jQuery.iDrop.checkhover(dragged);
+               }
+               return false;
+       },
+
+       build : function(o)
+       {
+               if (!jQuery.iDrag.helper) {
+                       jQuery('body',document).append('<div id="dragHelper"></div>');
+                       jQuery.iDrag.helper = jQuery('#dragHelper');
+                       var el = jQuery.iDrag.helper.get(0);
+                       var els = el.style;
+                       els.position = 'absolute';
+                       els.display = 'none';
+                       els.cursor = 'move';
+                       els.listStyle = 'none';
+                       els.overflow = 'hidden';
+                       if (window.ActiveXObject) {
+                               el.unselectable = "on";
+                       } else {
+                               els.mozUserSelect = 'none';
+                               els.userSelect = 'none';
+                               els.KhtmlUserSelect = 'none';
+                       }
+               }
+               if (!o) {
+                       o = {};
+               }
+               return this.each(
+                       function()
+                       {
+                               if (this.isDraggable || !jQuery.iUtil)
+                                       return;
+                               if (window.ActiveXObject) {
+                                       this.onselectstart = function(){return false;};
+                                       this.ondragstart = function(){return false;};
+                               }
+                               var el = this;
+                               var dhe = o.handle ? jQuery(this).find(o.handle) : jQuery(this);
+                               if(jQuery.browser.msie) {
+                                       dhe.each(
+                                               function()
+                                               {
+                                                       this.unselectable = "on";
+                                               }
+                                       );
+                               } else {
+                                       dhe.css('-moz-user-select', 'none');
+                                       dhe.css('user-select', 'none');
+                                       dhe.css('-khtml-user-select', 'none');
+                               }
+                               this.dragCfg = {
+                                       dhe: dhe,
+                                       revert : o.revert ? true : false,
+                                       ghosting : o.ghosting ? true : false,
+                                       so : o.so ? o.so : false,
+                                       si : o.si ? o.si : false,
+                                       insideParent : o.insideParent ? o.insideParent : false,
+                                       zIndex : o.zIndex ? parseInt(o.zIndex)||0 : false,
+                                       opacity : o.opacity ? parseFloat(o.opacity) : false,
+                                       fx : parseInt(o.fx)||null,
+                                       hpc : o.hpc ? o.hpc : false,
+                                       onDragModifier : {},
+                                       pointer : {},
+                                       onStart : o.onStart && o.onStart.constructor == Function ? o.onStart : false,
+                                       onStop : o.onStop && o.onStop.constructor == Function ? o.onStop : false,
+                                       onChange : o.onChange && o.onChange.constructor == Function ? o.onChange : false,
+                                       axis : /vertically|horizontally/.test(o.axis) ? o.axis : false,
+                                       snapDistance : o.snapDistance ? parseInt(o.snapDistance)||0 : 0,
+                                       cursorAt: o.cursorAt ? o.cursorAt : false,
+                                       autoSize : o.autoSize ? true : false,
+                                       frameClass : o.frameClass || false
+                                       
+                               };
+                               if (o.onDragModifier && o.onDragModifier.constructor == Function)
+                                       this.dragCfg.onDragModifier.user = o.onDragModifier;
+                               if (o.onDrag && o.onDrag.constructor == Function)
+                                       this.dragCfg.onDrag = o.onDrag;
+                               if (o.containment && ((o.containment.constructor == String && (o.containment == 'parent' || o.containment == 'document')) || (o.containment.constructor == Array && o.containment.length == 4) )) {
+                                       this.dragCfg.containment = o.containment;
+                               }
+                               if(o.fractions) {
+                                       this.dragCfg.fractions = o.fractions;
+                               }
+                               if(o.grid){
+                                       if(typeof o.grid == 'number'){
+                                               this.dragCfg.gx = parseInt(o.grid)||1;
+                                               this.dragCfg.gy = parseInt(o.grid)||1;
+                                       } else if (o.grid.length == 2) {
+                                               this.dragCfg.gx = parseInt(o.grid[0])||1;
+                                               this.dragCfg.gy = parseInt(o.grid[1])||1;
+                                       }
+                               }
+                               if (o.onSlide && o.onSlide.constructor == Function) {
+                                       this.dragCfg.onSlide = o.onSlide;
+                               }
+
+                               this.isDraggable = true;
+                               dhe.each(
+                                       function(){
+                                               this.dragElem = el;
+                                       }
+                               );
+                               dhe.bind('mousedown', jQuery.iDrag.draginit);
+                       }
+               )
+       }
+};
+
+/**
+ * Destroy an existing draggable on a collection of elements
+ * 
+ * @name DraggableDestroy
+ * @descr Destroy a draggable
+ * @type jQuery
+ * @cat Plugins/Interface
+ * @example $('#drag2').DraggableDestroy();
+ */
+
+jQuery.fn.extend(
+       {
+               DraggableDestroy : jQuery.iDrag.destroy,
+               Draggable : jQuery.iDrag.build
+       }
+);
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.impromptu.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.impromptu.js
new file mode 100644 (file)
index 0000000..f820bb9
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * jQuery Impromptu
+ * By: Trent Richardson [http://trentrichardson.com]
+ * Version 1.2
+ * Last Modified: 11/21/2007
+ * 
+ * Copyright 2007 Trent Richardson
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+jQuery.extend({        
+       ImpromptuDefaults: { prefix:'jqi', buttons:{ Ok:true }, loaded:function(){}, submit:function(){return true;}, callback:function(){}, container:'body', opacity:0.6, overlayspeed:'slow', promptspeed:'fast', show:'show'},
+       SetImpromptuDefaults: function(o){ 
+               jQuery.ImpromptuDefaults = jQuery.extend({},jQuery.ImpromptuDefaults,o);
+       },
+       prompt: function(m,o){
+               o = jQuery.extend({},jQuery.ImpromptuDefaults,o);
+               
+               var ie6 = (jQuery.browser.msie && jQuery.browser.version < 7);  
+               var b = (ie6)? jQuery(document.body):jQuery(o.container);       
+               var fade = '<div class="'+ o.prefix +'fade" id="'+ o.prefix +'fade"></div>';
+               if((jQuery.browser.msie && jQuery('object, applet').length > 0) || ie6)
+                       fade = '<iframe src="" class="'+ o.prefix +'fade" id="'+ o.prefix +'fade"></iframe>';
+               var msgbox = '<div class="'+ o.prefix +'" id="'+ o.prefix +'"><div class="'+ o.prefix +'container"><div class="'+ o.prefix +'message">'+ m +'</div><div class="'+ o.prefix +'buttons" id="'+ o.prefix +'buttons">';
+               jQuery.each(o.buttons,function(k,v){ msgbox += '<button name="'+ o.prefix +'button'+ k +'" id="'+ o.prefix +'button'+ k +'" value="'+ v +'">'+ k +'</button>'}) ;
+               msgbox += '</div></div></div>';
+               
+               var jqi = b.prepend(msgbox).children('#'+ o.prefix);
+               var jqif = b.prepend(fade).children('#'+ o.prefix +'fade');
+               
+               //ie6 calculation functions
+               var getfoffset = function(){ return (document.documentElement.scrollTop || document.body.scrollTop) + 'px'; };
+               var getjoffset = function(){ return (document.documentElement.scrollTop || document.body.scrollTop) + Math.round(15 * (document.documentElement.offsetHeight || document.body.clientHeight) / 100) + 'px'; };
+               var ie6scroll = function(){ jqif.css({ top: getfoffset() }); jqi.css({ top: getjoffset() }); };
+               
+               jqif.css({ position: "absolute", height: (ie6)? "100%":b.height(), width: "100%", top: (ie6)? getfoffset():0, left: 0, right: 0, bottom: 0, zIndex: 998, display: "none", opacity: o.opacity });
+               jqi.css({ position: (ie6)? "absolute" : "fixed", top: (ie6)? getjoffset():"30%", left: "50%", display: "none", zIndex: 999, marginLeft: ((((jqi.css("paddingLeft").split("px")[0]*1) + jqi.width())/2)*-1) });
+                       
+               jQuery('#'+ o.prefix +'buttons').children('button').click(function(){ 
+                       var msg = jqi.children('.'+ o.prefix +'container').children('.'+ o.prefix +'message');
+                       var clicked = o.buttons[jQuery(this).text()];   
+                       if(o.submit(clicked,msg)){              
+                               jqi.remove(); 
+                               if(ie6)jQuery(window).unbind('scroll',ie6scroll);//ie6, remove the scroll event
+                               jqif.fadeOut(o.overlayspeed,function(){
+                                       jqif.remove();
+                                       o.callback(clicked,msg);
+                               });
+                       }
+               });
+                               
+               if(ie6) jQuery(window).scroll(ie6scroll);//ie6, add a scroll event to fix position:fixed
+               jqif.fadeIn(o.overlayspeed);
+               jqi[o.show](o.promptspeed,o.loaded);
+               return jqi;
+       }       
+});
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.iutil.pack.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.iutil.pack.js
new file mode 100644 (file)
index 0000000..05a5b04
--- /dev/null
@@ -0,0 +1,13 @@
+/**
+ * Interface Elements for jQuery
+ * utility function
+ *
+ * http://interface.eyecon.ro
+ *
+ * Copyright (c) 2006 Stefan Petre
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ *
+ */
+eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('9.J={1C:6(e){4 x=0;4 y=0;4 7=e.Y;4 12=1H;c(9(e).8(\'A\')==\'T\'){4 N=7.B;4 Q=7.z;12=1f;7.B=\'1r\';7.A=\'1q\';7.z=\'1d\'}4 3=e;R(3){x+=3.1h+(3.O&&!9.1m.1i?d(3.O.17)||0:0);y+=3.1n+(3.O&&!9.1m.1i?d(3.O.18)||0:0);3=3.1t}3=e;R(3&&3.1e&&3.1e.16()!=\'f\'){x-=3.u||0;y-=3.F||0;3=3.1D}c(12==1f){7.A=\'T\';7.z=Q;7.B=N}a{x:x,y:y}},1B:6(3){4 x=0,y=0;R(3){x+=3.1h||0;y+=3.1n||0;3=3.1t}a{x:x,y:y}},1s:6(e){4 w=9.8(e,\'1E\');4 h=9.8(e,\'1G\');4 o=0;4 q=0;4 7=e.Y;c(9(e).8(\'A\')!=\'T\'){o=e.V;q=e.U}p{4 N=7.B;4 Q=7.z;7.B=\'1r\';7.A=\'1q\';7.z=\'1d\';o=e.V;q=e.U;7.A=\'T\';7.z=Q;7.B=N}a{w:w,h:h,o:o,q:q}},1F:6(3){a{o:3.V||0,q:3.U||0}},1I:6(e){4 h,w,C;c(e){w=e.I;h=e.G}p{C=5.j;w=1c.14||P.14||(C&&C.I)||5.f.I;h=1c.10||P.10||(C&&C.G)||5.f.G}a{w:w,h:h}},1p:6(e){4 t=0,l=0,w=0,h=0,s=0,E=0;c(e&&e.1u.16()!=\'f\'){t=e.F;l=e.u;w=e.15;h=e.W;s=0;E=0}p{c(5.j){t=5.j.F;l=5.j.u;w=5.j.15;h=5.j.W}p c(5.f){t=5.f.F;l=5.f.u;w=5.f.15;h=5.f.W}s=P.14||5.j.I||5.f.I||0;E=P.10||5.j.G||5.f.G||0}a{t:t,l:l,w:w,h:h,s:s,E:E}},1v:6(e,D){4 3=9(e);4 t=3.8(\'1w\')||\'\';4 r=3.8(\'1x\')||\'\';4 b=3.8(\'1A\')||\'\';4 l=3.8(\'1z\')||\'\';c(D)a{t:d(t)||0,r:d(r)||0,b:d(b)||0,l:d(l)};p a{t:t,r:r,b:b,l:l}},1y:6(e,D){4 3=9(e);4 t=3.8(\'1J\')||\'\';4 r=3.8(\'1M\')||\'\';4 b=3.8(\'27\')||\'\';4 l=3.8(\'28\')||\'\';c(D)a{t:d(t)||0,r:d(r)||0,b:d(b)||0,l:d(l)};p a{t:t,r:r,b:b,l:l}},26:6(e,D){4 3=9(e);4 t=3.8(\'18\')||\'\';4 r=3.8(\'22\')||\'\';4 b=3.8(\'23\')||\'\';4 l=3.8(\'17\')||\'\';c(D)a{t:d(t)||0,r:d(r)||0,b:d(b)||0,l:d(l)||0};p a{t:t,r:r,b:b,l:l}},2e:6(L){4 x=L.2d||(L.2b+(5.j.u||5.f.u))||0;4 y=L.2c||(L.29+(5.j.F||5.f.F))||0;a{x:x,y:y}},X:6(g,13){13(g);g=g.1O;R(g){9.J.X(g,13);g=g.1L}},1N:6(g){9.J.X(g,6(3){19(4 Z 1T 3){c(1Z 3[Z]===\'6\'){3[Z]=1a}}})},1X:6(3,H){4 k=9.J.1p();4 11=9.J.1s(3);c(!H||H==\'1W\')9(3).8({1U:k.t+((1g.1o(k.h,k.E)-k.t-11.q)/2)+\'1j\'});c(!H||H==\'20\')9(3).8({1Y:k.l+((1g.1o(k.w,k.s)-k.l-11.o)/2)+\'1j\'})},2f:6(3,1l){4 1k=9(\'25[@M*="S"]\',3||5),S;1k.24(6(){S=K.M;K.M=1l;K.Y.2a="21:1R.1P.1V(M=\'"+S+"\')"})}};[].1b||(1S.1Q.1b=6(v,n){n=(n==1a)?0:n;4 m=K.1K;19(4 i=n;i<m;i++)c(K[i]==v)a i;a-1});',62,140,'|||el|var|document|function|es|css|jQuery|return||if|parseInt||body|nodeEl|||documentElement|clientScroll||||wb|else|hb||iw||scrollLeft|||||position|display|visibility|de|toInteger|ih|scrollTop|clientHeight|axis|clientWidth|iUtil|this|event|src|oldVisibility|currentStyle|self|oldPosition|while|png|none|offsetHeight|offsetWidth|scrollHeight|traverseDOM|style|attr|innerHeight|windowSize|restoreStyles|func|innerWidth|scrollWidth|toLowerCase|borderLeftWidth|borderTopWidth|for|null|indexOf|window|absolute|tagName|true|Math|offsetLeft|opera|px|images|emptyGIF|browser|offsetTop|max|getScroll|block|hidden|getSize|offsetParent|nodeName|getMargins|marginTop|marginRight|getPadding|marginLeft|marginBottom|getPositionLite|getPosition|parentNode|width|getSizeLite|height|false|getClient|paddingTop|length|nextSibling|paddingRight|purgeEvents|firstChild|Microsoft|prototype|DXImageTransform|Array|in|top|AlphaImageLoader|vertically|centerEl|left|typeof|horizontally|progid|borderRightWidth|borderBottomWidth|each|img|getBorder|paddingBottom|paddingLeft|clientY|filter|clientX|pageY|pageX|getPointer|fixPNG'.split('|'),0,{}))
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.tablesorter.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.tablesorter.js
new file mode 100644 (file)
index 0000000..c752077
--- /dev/null
@@ -0,0 +1,861 @@
+/*
+ * 
+ * TableSorter 2.0 - Client-side table sorting with ease!
+ * Version 2.0.1
+ * @requires jQuery v1.2.1
+ * 
+ * Copyright (c) 2007 Christian Bach
+ * Examples and docs at: http://tablesorter.com
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ * 
+ */
+/**
+ *
+ * @description Create a sortable table with multi-column sorting capabilitys
+ * 
+ * @example $('table').tablesorter();
+ * @desc Create a simple tablesorter interface.
+ *
+ * @example $('table').tablesorter({ sortList:[[0,0],[1,0]] });
+ * @desc Create a tablesorter interface and sort on the first and secound column in ascending order.
+ * 
+ * @example $('table').tablesorter({ headers: { 0: { sorter: false}, 1: {sorter: false} } });
+ * @desc Create a tablesorter interface and disableing the first and secound column headers.
+ * 
+ * @example $('table').tablesorter({ 0: {sorter:"integer"}, 1: {sorter:"currency"} });
+ * @desc Create a tablesorter interface and set a column parser for the first and secound column.
+ * 
+ * 
+ * @param Object settings An object literal containing key/value pairs to provide optional settings.
+ * 
+ * @option String cssHeader (optional)                         A string of the class name to be appended to sortable tr elements in the thead of the table. 
+ *                                                                                             Default value: "header"
+ * 
+ * @option String cssAsc (optional)                    A string of the class name to be appended to sortable tr elements in the thead on a ascending sort. 
+ *                                                                                             Default value: "headerSortUp"
+ * 
+ * @option String cssDesc (optional)                   A string of the class name to be appended to sortable tr elements in the thead on a descending sort. 
+ *                                                                                             Default value: "headerSortDown"
+ * 
+ * @option String sortInitialOrder (optional)  A string of the inital sorting order can be asc or desc. 
+ *                                                                                             Default value: "asc"
+ * 
+ * @option String sortMultisortKey (optional)  A string of the multi-column sort key. 
+ *                                                                                             Default value: "shiftKey"
+ * 
+ * @option String textExtraction (optional)    A string of the text-extraction method to use. 
+ *                                                                                             For complex html structures inside td cell set this option to "complex", 
+ *                                                                                             on large tables the complex option can be slow. 
+ *                                                                                             Default value: "simple"
+ * 
+ * @option Object headers (optional)                   An array containing the forces sorting rules. 
+ *                                                                                             This option let's you specify a default sorting rule. 
+ *                                                                                             Default value: null
+ * 
+ * @option Array sortList (optional)                   An array containing the forces sorting rules. 
+ *                                                                                             This option let's you specify a default sorting rule. 
+ *                                                                                             Default value: null
+ * 
+ * @option Array sortForce (optional)                  An array containing the forces sorting rules. 
+ *                                                                                             This option let's you specify a default sorting rule. 
+ *                                                                                             Default value: null
+ *  
+ * 
+ * @option Boolean widthFixed (optional)               Boolean flag indicating if tablesorter should apply fixed widths to the table columns.
+ *                                                                                             This is usefull when using the pager companion plugin.
+ *                                                                                             This options requires the dimension jquery plugin.
+ *                                                                                             Default value: false
+ *
+ * @option Boolean cancelSelection (optional)  Boolean flag indicating if tablesorter should cancel selection of the table headers text.
+ *                                                                                             Default value: true
+ *
+ * @option Boolean debug (optional)                    Boolean flag indicating if tablesorter should display debuging information usefull for development.
+ *
+ * @type jQuery
+ *
+ * @name tablesorter
+ * 
+ * @cat Plugins/Tablesorter
+ * 
+ * @author Christian Bach/christian.bach@polyester.se
+ */
+
+(function($) {
+       $.extend({
+               tablesorter: new function() {
+                       
+                       var parsers = [], widgets = [];
+                       
+                       this.defaults = {
+                               cssHeader: "header",
+                               cssAsc: "headerSortUp",
+                               cssDesc: "headerSortDown",
+                               sortInitialOrder: "asc",
+                               sortMultiSortKey: "shiftKey",
+                               sortForce: null,
+                               textExtraction: "simple",
+                               parsers: {}, 
+                               widgets: [],            
+                               widgetZebra: {css: ["even","odd"]},
+                               headers: {},
+                               widthFixed: false,
+                               cancelSelection: true,
+                               sortList: [],
+                               headerList: [],
+                               dateFormat: "us",
+                               debug: false
+                       };
+                       
+                       /* debuging utils */
+                       function benchmark(s,d) {
+                               log(s + "," + (new Date().getTime() - d.getTime()) + "ms");
+                       }
+                       
+                       this.benchmark = benchmark;
+                       
+                       function log(s) {
+                               if (typeof console != "undefined" && typeof console.debug != "undefined") {
+                                       console.log(s);
+                               } else {
+                                       alert(s);
+                               }
+                       }
+                                               
+                       /* parsers utils */
+                       function buildParserCache(table,$headers) {
+                               
+                               if(table.config.debug) { var parsersDebug = ""; }
+                               
+                               var rows = table.tBodies[0].rows;
+                               
+                               if(table.tBodies[0].rows[0]) {
+
+                                       var list = [], cells = rows[0].cells, l = cells.length;
+                                       
+                                       for (var i=0;i < l; i++) {
+                                               var p = false;
+                                               
+                                               if($.meta && ($($headers[i]).data() && $($headers[i]).data().sorter)  ) {
+                                               
+                                                       p = getParserById($($headers[i]).data().sorter);        
+                                               
+                                               } else if((table.config.headers[i] && table.config.headers[i].sorter)) {
+       
+                                                       p = getParserById(table.config.headers[i].sorter);
+                                               }
+                                               if(!p) {
+                                                       p = detectParserForColumn(table.config,cells[i]);
+                                               }
+       
+                                               if(table.config.debug) { parsersDebug += "column:" + i + " parser:" +p.id + "\n"; }
+       
+                                               list.push(p);
+                                       }
+                               }
+                               
+                               if(table.config.debug) { log(parsersDebug); }
+
+                               return list;
+                       };
+                       
+                       function detectParserForColumn(config,node) {
+                               var l = parsers.length;
+                               for(var i=1; i < l; i++) {
+                                       if(parsers[i].is($.trim(getElementText(config,node)))) {
+                                               return parsers[i];
+                                       }
+                               }
+                               
+                               // 0 is always the generic parser (text)
+                               return parsers[0];
+                       }
+                       
+                       function getParserById(name) {
+                               var l = parsers.length;
+                               for(var i=0; i < l; i++) {
+                                       if(parsers[i].id.toLowerCase() == name.toLowerCase()) { 
+                                               return parsers[i];
+                                       }
+                               }
+                               return false;
+                       }
+                       
+                       /* utils */
+                       function buildCache(table) {
+                               
+                               if(table.config.debug) { var cacheTime = new Date(); }
+                               
+                               
+                               var totalRows = (table.tBodies[0] && table.tBodies[0].rows.length) || 0,
+                                       totalCells = (table.tBodies[0].rows[0] && table.tBodies[0].rows[0].cells.length) || 0,
+                                       parsers = table.config.parsers, 
+                                       cache = {row: [], normalized: []};
+                               
+                                       for (var i=0;i < totalRows; ++i) {
+                                       
+                                               /** Add the table data to main data array */
+                                               var c = table.tBodies[0].rows[i], cols = [];
+                                       
+                                               cache.row.push($(c));
+                                               
+                                               for(var j=0; j < totalCells; ++j) {
+                                                       cols.push(parsers[j].format(getElementText(table.config,c.cells[j]),table,c.cells[j])); 
+                                               }
+                                                                                               
+                                               cols.push(i); // add position for rowCache
+                                               cache.normalized.push(cols);
+                                               cols = null;
+                                       };
+                               
+                               if(table.config.debug) { benchmark("Building cache for " + totalRows + " rows:", cacheTime); }
+                               
+                               return cache;
+                       };
+                       
+                       function getElementText(config,node) {
+                               
+                               if(!node) return "";
+                                                               
+                               var t = "";
+                               
+                               if(config.textExtraction == "simple") {
+                                       if(node.childNodes[0] && node.childNodes[0].hasChildNodes()) {
+                                               t = node.childNodes[0].innerHTML;
+                                       } else {
+                                               t = node.innerHTML;
+                                       }
+                               } else {
+                                       if(typeof(config.textExtraction) == "function") {
+                                               t = config.textExtraction(node);
+                                       } else { 
+                                               t = $(node).text();
+                                       }       
+                               }
+                               return t;
+                       }
+                       
+                       function appendToTable(table,cache) {
+                               
+                               if(table.config.debug) {var appendTime = new Date()}
+                               
+                               var c = cache, 
+                                       r = c.row, 
+                                       n= c.normalized, 
+                                       totalRows = n.length, 
+                                       checkCell = (n[0].length-1), 
+                                       tableBody = $(table.tBodies[0]),
+                                       rows = [];
+                               
+                               // clear the table body
+                               //$.tablesorter.clearTableBody(table);
+                               
+                               
+                               
+                                                               
+                               for (var i=0;i < totalRows; i++) {
+                                       rows.push(r[n[i][checkCell]]);  
+                                       if(!table.config.appender) {
+                                               
+                                               var o = r[n[i][checkCell]];
+                                               var l = o.length;
+                                               for(var j=0; j < l; j++) {
+                                                       
+                                                       tableBody[0].appendChild(o[j]);
+                                               
+                                               }
+                                               
+                                               //tableBody.append(r[n[i][checkCell]]);
+                                       }
+                               }       
+                               
+                               if(table.config.appender) {
+                               
+                                       table.config.appender(table,rows);      
+                               }
+                               
+                               rows = null;
+                               
+                               if(table.config.debug) { benchmark("Rebuilt table:", appendTime); }
+                                                               
+                               //apply table widgets
+                               applyWidget(table);
+                       };
+                       
+                       function buildHeaders(table) {
+                               
+                               if(table.config.debug) { var time = new Date(); }
+                               
+                               var meta = ($.meta) ? true : false, tableHeadersRows = [];
+                       
+                               for(var i = 0; i < table.tHead.rows.length; i++) { tableHeadersRows[i]=0; };
+                               
+                               $tableHeaders = $("thead th",table);
+               
+                               $tableHeaders.each(function(index) {
+                                                       
+                                       this.count = 0;
+                                       this.column = index;
+                                       this.order = formatSortingOrder(table.config.sortInitialOrder);
+                                       
+                                       if(checkHeaderMetadata(this) || checkHeaderOptions(table,index)) this.sortDisabled = true;
+                                       
+                                       if(!this.sortDisabled) {
+                                               $(this).addClass(table.config.cssHeader);
+                                       }
+                                       
+                                       // add cell to headerList
+                                       table.config.headerList[index]= this;
+                               });
+                               
+                               if(table.config.debug) { benchmark("Built headers:", time); log($tableHeaders); }
+                               
+                               return $tableHeaders;
+                               
+                       };
+                                               
+                       function checkCellColSpan(table, rows, row) {
+                var arr = [], r = table.tHead.rows, c = r[row].cells;
+                               
+                               for(var i=0; i < c.length; i++) {
+                                       var cell = c[i];
+                                       
+                                       if ( cell.colSpan > 1) { 
+                                               arr = arr.concat(checkCellColSpan(table, headerArr,row++));
+                                       } else  {
+                                               if(table.tHead.length == 1 || (cell.rowSpan > 1 || !r[row+1])) {
+                                                       arr.push(cell);
+                                               }
+                                               //headerArr[row] = (i+row);
+                                       }
+                               }
+                               return arr;
+                       };
+                       
+                       function checkHeaderMetadata(cell) {
+                               if(($.meta) && ($(cell).data().sorter === false)) { return true; };
+                               return false;
+                       }
+                       
+                       function checkHeaderOptions(table,i) {  
+                               if((table.config.headers[i]) && (table.config.headers[i].sorter === false)) { return true; };
+                               return false;
+                       }
+                       
+                       function applyWidget(table) {
+                               var c = table.config.widgets;
+                               var l = c.length;
+                               for(var i=0; i < l; i++) {
+                                       
+                                       getWidgetById(c[i]).format(table);
+                               }
+                               
+                       }
+                       
+                       function getWidgetById(name) {
+                               var l = widgets.length;
+                               for(var i=0; i < l; i++) {
+                                       if(widgets[i].id.toLowerCase() == name.toLowerCase() ) {
+                                               return widgets[i]; 
+                                       }
+                               }
+                       };
+                       
+                       function formatSortingOrder(v) {
+                               
+                               if(typeof(v) != "Number") {
+                                       i = (v.toLowerCase() == "desc") ? 1 : 0;
+                               } else {
+                                       i = (v == (0 || 1)) ? v : 0;
+                               }
+                               return i;
+                       }
+                       
+                       function isValueInArray(v, a) {
+                               var l = a.length;
+                               for(var i=0; i < l; i++) {
+                                       if(a[i][0] == v) {
+                                               return true;    
+                                       }
+                               }
+                               return false;
+                       }
+                               
+                       function setHeadersCss(table,$headers, list, css) {
+                               // remove all header information
+                               $headers.removeClass(css[0]).removeClass(css[1]);
+                               
+                               var h = [];
+                               $headers.each(function(offset) {
+                                               if(!this.sortDisabled) {
+                                                       h[this.column] = $(this);                                       
+                                               }
+                               });
+                               
+                               var l = list.length; 
+                               for(var i=0; i < l; i++) {
+                                       h[list[i][0]].addClass(css[list[i][1]]);
+                               }
+                       }
+                       
+                       function fixColumnWidth(table,$headers) {
+                               var c = table.config;
+                               if(c.widthFixed) {
+                                       var colgroup = $('<colgroup>');
+                                       $("tr:first td",table.tBodies[0]).each(function() {
+                                               colgroup.append($('<col>').css('width',$(this).width()));
+                                       });
+                                       $(table).prepend(colgroup);
+                               };
+                       }
+                       
+                       function updateHeaderSortCount(table,sortList) {
+                               var c = table.config, l = sortList.length;
+                               for(var i=0; i < l; i++) {
+                                       var s = sortList[i], o = c.headerList[s[0]];
+                                       o.count = s[1];
+                                       o.count++;
+                               }
+                       }
+                       
+                       /* sorting methods */
+                       function multisort(table,sortList,cache) {
+                               
+                               
+                               if(table.config.debug) { var sortTime = new Date(); }
+                               
+                               var dynamicExp = "var sortWrapper = function(a,b) {", l = sortList.length;
+                                       
+                               for(var i=0; i < l; i++) {
+                                       
+                                       var c = sortList[i][0];
+                                       var order = sortList[i][1];
+                                       var s = (getCachedSortType(table.config.parsers,c) == "text") ? ((order == 0) ? "sortText" : "sortTextDesc") : ((order == 0) ? "sortNumeric" : "sortNumericDesc");
+                                       
+                                       var e = "e" + i;
+                                       
+                                       dynamicExp += "var " + e + " = " + s + "(a[" + c + "],b[" + c + "]); ";
+                                       dynamicExp += "if(" + e + ") { return " + e + "; } ";
+                                       dynamicExp += "else { ";
+                               }
+                               
+                               // if value is the same keep orignal order      
+                               var orgOrderCol = cache.normalized[0].length - 1;
+                               dynamicExp += "return a[" + orgOrderCol + "]-b[" + orgOrderCol + "];";
+                                               
+                               for(var i=0; i < l; i++) {
+                                       dynamicExp += "}; ";
+                               }
+                               
+                               dynamicExp += "return 0; ";     
+                               dynamicExp += "}; ";    
+                               
+                               eval(dynamicExp);
+                               
+                               cache.normalized.sort(sortWrapper);
+                               
+                               if(table.config.debug) { benchmark("Sorting on " + sortList.toString() + " and dir " + order+ " time:", sortTime); }
+                               
+                               return cache;
+                       };
+                       
+                       function sortText(a,b) {
+                               return ((a < b) ? -1 : ((a > b) ? 1 : 0));
+                       };
+                       
+                       function sortTextDesc(a,b) {
+                               return ((b < a) ? -1 : ((b > a) ? 1 : 0));
+                       };      
+                       
+                       function sortNumeric(a,b) {
+                               return a-b;
+                       };
+                       
+                       function sortNumericDesc(a,b) {
+                               return b-a;
+                       };
+                       
+                       function getCachedSortType(parsers,i) {
+                               return parsers[i].type;
+                       };
+                       
+                       /* public methods */
+                       this.construct = function(settings) {
+
+                               return this.each(function() {
+                                       
+                                       if(!this.tHead || !this.tBodies) return;
+                                       
+                                       var $this, $document,$headers, cache, config, shiftDown = 0, sortOrder;
+                                       
+                                       this.config = {};
+                                       
+                                       config = $.extend(this.config, $.tablesorter.defaults, settings);
+                                       
+                                       // store common expression for speed                                    
+                                       $this = $(this);
+                                       
+                                       // build headers
+                                       $headers = buildHeaders(this);
+                                       
+                                       // try to auto detect column type, and store in tables config
+                                       this.config.parsers = buildParserCache(this,$headers);
+                                       
+                                       
+                                       // build the cache for the tbody cells
+                                       cache = buildCache(this);
+                                       
+                                       // get the css class names, could be done else where.
+                                       var sortCSS = [config.cssDesc,config.cssAsc];
+                                       
+                                       // fixate columns if the users supplies the fixedWidth option
+                                       fixColumnWidth(this);
+                                       
+                                       // apply event handling to headers
+                                       // this is to big, perhaps break it out?
+                                       $headers.click(function(e) {
+                                               
+                                               var totalRows = ($this[0].tBodies[0] && $this[0].tBodies[0].rows.length) || 0;
+                                               
+                                               if(!this.sortDisabled && totalRows > 0) {
+                                                       // store exp, for speed
+                                                       var $cell = $(this);
+       
+                                                       // get current column index
+                                                       var i = this.column;
+                                                       
+                                                       // get current column sort order
+                                                       this.order = this.count++ % 2;
+                                                       
+                                                       // user only whants to sort on one column
+                                                       if(!e[config.sortMultiSortKey]) {
+                                                               
+                                                               // flush the sort list
+                                                               config.sortList = [];
+                                                               
+                                                               if(config.sortForce != null) {
+                                                                       var a = config.sortForce; 
+                                                                       for(var j=0; j < a.length; j++) {       
+                                                                               config.sortList.push(a[j]);     
+                                                                       }
+                                                               }
+                                                               
+                                                               // add column to sort list
+                                                               config.sortList.push([i,this.order]);
+                                                       
+                                                       // multi column sorting 
+                                                       } else {
+                                                               // the user has clicked on an all ready sortet column.
+                                                               if(isValueInArray(i,config.sortList)) {  
+                                                                       
+                                                                       // revers the sorting direction for all tables.
+                                                                       for(var j=0; j < config.sortList.length; j++) {
+                                                                               var s = config.sortList[j], o = config.headerList[s[0]];
+                                                                               if(s[0] == i) {
+                                                                                       o.count = s[1];
+                                                                                       o.count++;
+                                                                                       s[1] = o.count % 2;
+                                                                               }
+                                                                       }       
+                                                               } else {
+                                                                       // add column to sort list array
+                                                                       config.sortList.push([i,this.order]);
+                                                               }
+                                                       };
+                                                       
+                                                       // trigger sortstart
+                                                       $this.trigger("sortStart");
+                                                       
+                                                       //set css for headers
+                                                       setHeadersCss($this[0],$headers,config.sortList,sortCSS);
+                                                       
+                                                       // javascript threading..
+                                                       setTimeout(function() {
+                                                               // sort the table and append it to the dom
+                                                               appendToTable($this[0],multisort($this[0],config.sortList,cache));
+                                                               // trigger sortstart
+                                                               $this.trigger("sortEnd");
+                                                       }, 0);
+                                                       // stop normal event by returning false
+                                                       return false;
+                                               }
+                                       // cancel selection     
+                                       }).mousedown(function() {
+                                               if(config.cancelSelection) {
+                                                       this.onselectstart = function() {return false};
+                                                       return false;
+                                               }
+                                       });
+                                       
+                                       // apply easy methods that trigger binded events
+                                       $this.bind("update",function() {
+                                               
+                                               // rebuild parsers.
+                                               this.config.parsers = buildParserCache(this,$headers);
+                                               
+                                               // rebuild the cache map
+                                               cache = buildCache(this);
+                                               
+                                       }).bind("sorton",function(e,list) {
+                                       
+                                               config.sortList = list;
+                                               
+                                               // update and store the sortlist
+                                               var sortList = config.sortList;
+                                               
+                                               // update header count index
+                                               updateHeaderSortCount(this,sortList);
+                                               
+                                               //set css for headers
+                                               setHeadersCss(this,$headers,sortList,sortCSS);
+                                               
+                                               // sort the table and append it to the dom
+                                               appendToTable(this,multisort(this,sortList,cache));
+                                               
+                                       }).bind("appendCache",function() {
+                                               
+                                               appendToTable(this,cache);
+                                       
+                                       }).bind("applyWidgetId",function(e,id) {
+                                               
+                                               getWidgetById(id).format(this);
+                                               
+                                       }).bind("applyWidgets",function() {
+                                               // apply widgets
+                                               applyWidget(this);
+                                       });
+                                       
+                                       if($.meta && ($(this).data() && $(this).data().sortlist)) {
+                                               config.sortList = $(this).data().sortlist;
+                                       }
+                                       // if user has supplied a sort list to constructor.
+                                       if(config.sortList.length > 0) {
+                                               $this.trigger("sorton",[config.sortList]);      
+                                       }
+                                       
+                                       // apply widgets
+                                       applyWidget(this);
+                               });
+                       };
+                       
+                       this.addParser = function(parser) {
+                               var l = parsers.length, a = true;
+                               for(var i=0; i < l; i++) {
+                                       if(parsers[i].id.toLowerCase() == parser.id.toLowerCase()) {
+                                               a = false;
+                                       }
+                               }
+                               if(a) { parsers.push(parser); };
+                       };
+                       
+                       this.addWidget = function(widget) {
+                               widgets.push(widget);
+                       };
+                       
+                       this.formatFloat = function(s) {
+
+                               var i = parseFloat(s);
+                               return (isNaN(i)) ? 0 : i;
+                       };
+                       this.formatInt = function(s) {
+                               var i = parseInt(s);
+                               return (isNaN(i)) ? 0 : i;
+                       };
+                       
+                       this.clearTableBody = function(table) {
+                               
+                               if($.browser.msie) {
+                                       
+                                       function empty() {
+                                       
+                                               while ( this.firstChild ) this.removeChild( this.firstChild );
+               
+                                       }
+                                       
+                                       empty.apply(table.tBodies[0]);
+                                       
+                               } else {
+                                       table.tBodies[0].innerHTML = "";
+                               }
+                       };
+               }
+       });
+       
+       // extend plugin scope
+       $.fn.extend({
+        tablesorter: $.tablesorter.construct
+       });
+       
+       var ts = $.tablesorter;
+       
+       // add default parsers
+       ts.addParser({
+               id: "text",
+               is: function(s) {
+                       return true;
+               },
+               format: function(s) {
+                       return $.trim(s.toLowerCase());
+               },
+               type: "text"
+       });
+       
+       ts.addParser({
+               id: "integer",
+               is: function(s) {
+                       return /^\d+$/.test(s);
+               },
+               format: function(s) {
+                       return $.tablesorter.formatFloat(s);
+               },
+               type: "numeric"
+       });
+       
+       ts.addParser({
+               id: "currency",
+               is: function(s) {
+                       return /^[£$€?.]/.test(s);
+               },
+               format: function(s) {
+                       return $.tablesorter.formatFloat(s.replace(new RegExp(/[^0-9.]/g),""));
+               },
+               type: "numeric"
+       });
+       
+       ts.addParser({
+               id: "floating",
+               is: function(s) {
+                       return s.match(new RegExp(/^(\+|-)?[0-9]+\.[0-9]+((E|e)(\+|-)?[0-9]+)?$/));
+               },
+               format: function(s) {
+                       return $.tablesorter.formatFloat(s.replace(new RegExp(/,/),""));
+               },
+               type: "numeric"
+       });
+       
+       ts.addParser({
+               id: "ipAddress",
+               is: function(s) {
+                       return /^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);
+               },
+               format: function(s) {
+                       var a = s.split("."), r = "", l = a.length;
+                       for(var i = 0; i < l; i++) {
+                               var item = a[i];
+                               if(item.length == 2) {
+                                       r += "0" + item;
+                               } else {
+                                       r += item;
+                               }
+                       }
+                       return $.tablesorter.formatFloat(r);
+               },
+               type: "numeric"
+       });
+       
+       ts.addParser({
+               id: "url",
+               is: function(s) {
+                       return /^(https?|ftp|file):\/\/$/.test(s);
+               },
+               format: function(s) {
+                       return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));
+               },
+               type: "text"
+       });
+       
+       ts.addParser({
+               id: "isoDate",
+               is: function(s) {
+                       return /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);
+               },
+               format: function(s) {
+                       return $.tablesorter.formatFloat((s != "") ? new Date(s.replace(new RegExp(/-/g),"/")).getTime() : "0");
+               },
+               type: "numeric"
+       });
+               
+       ts.addParser({
+               id: "percent",
+               is: function(s) {
+                       return /^\d{1,3}%$/.test(s);
+               },
+               format: function(s) {
+                       return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));
+               },
+               type: "numeric"
+       });
+
+       ts.addParser({
+               id: "usLongDate",
+               is: function(s) {
+                       return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));
+               },
+               format: function(s) {
+                       return $.tablesorter.formatFloat(new Date(s).getTime());
+               },
+               type: "numeric"
+       });
+
+       ts.addParser({
+               id: "shortDate",
+               is: function(s) {
+                       return /\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);
+               },
+               format: function(s,table) {
+                       var c = table.config;
+                       s = s.replace(/\-/g,"/");
+                       if(c.dateFormat == "us") {
+                               // reformat the string in ISO format
+                               s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$1/$2");
+                       } else if(c.dateFormat == "uk") {
+                               //reformat the string in ISO format
+                               s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$2/$1");
+                       } else if(c.dateFormat == "dd/mm/yy" || c.dateFormat == "dd-mm-yy") {
+                               s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/, "$1/$2/$3");     
+                       }
+                       return $.tablesorter.formatFloat(new Date(s).getTime());
+               },
+               type: "numeric"
+       });
+
+       ts.addParser({
+           id: "time",
+           is: function(s) {
+               return /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);
+           },
+           format: function(s) {
+               return $.tablesorter.formatFloat(new Date("2000/01/01 " + s).getTime());
+           },
+         type: "numeric"
+       });
+       
+       
+       ts.addParser({
+           id: "metadata",
+           is: function(s) {
+               return false;
+           },
+           format: function(s,table,cell) {
+                       var c = table.config, p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName;
+               return $(cell).data()[p];
+           },
+         type: "numeric"
+       });
+       
+       // add default widgets
+       ts.addWidget({
+               id: "zebra",
+               format: function(table) {
+                       if(table.config.debug) { var time = new Date(); }
+                       $("tr:visible",table.tBodies[0])
+               .filter(':even')
+               .removeClass(table.config.widgetZebra.css[1]).addClass(table.config.widgetZebra.css[0])
+               .end().filter(':odd')
+               .removeClass(table.config.widgetZebra.css[0]).addClass(table.config.widgetZebra.css[1]);
+                       if(table.config.debug) { $.tablesorter.benchmark("Applying Zebra widget", time); }
+               }
+       });
+       
+})(jQuery);
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.tablesorter.pack.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/jquery/jquery.tablesorter.pack.js
new file mode 100644 (file)
index 0000000..36040b7
--- /dev/null
@@ -0,0 +1 @@
+eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(8($){$.1V({I:D 8(){7 C=[],1d=[];k.2v={28:"3Z",2b:"48",29:"49",2P:"4a",2D:"4b",1I:1E,1w:"25",C:{},1d:[],1m:{S:["2c","2L"]},x:{},2u:K,2Q:13,u:[],1y:[],1l:"2O",J:K};8 17(s,d){1h(s+","+(D T().1e()-d.1e())+"4c")}k.17=17;8 1h(s){q(1u 1P!="2S"&&1u 1P.J!="2S"){1P.1h(s)}N{2V(s)}}8 1T(6,$x){q(6.f.J){7 1O=""}7 G=6.L[0].G;q(6.L[0].G[0]){7 Z=[],12=G[0].12,l=12.w;y(7 i=0;i<l;i++){7 p=K;q($.1o&&($($x[i]).16()&&$($x[i]).16().1g)){p=1K($($x[i]).16().1g)}N q((6.f.x[i]&&6.f.x[i].1g)){p=1K(6.f.x[i].1g)}q(!p){p=22(6.f,12[i])}q(6.f.J){1O+="1D:"+i+" 1B:"+p.B+"\\n"}Z.R(p)}}q(6.f.J){1h(1O)}m Z};8 22(f,V){7 l=C.w;y(7 i=1;i<l;i++){q(C[i].O($.1M(1Q(f,V)))){m C[i]}}m C[0]}8 1K(1x){7 l=C.w;y(7 i=0;i<l;i++){q(C[i].B.14()==1x.14()){m C[i]}}m K}8 1U(6){q(6.f.J){7 23=D T()}7 19=(6.L[0]&&6.L[0].G.w)||0,2r=(6.L[0].G[0]&&6.L[0].G[0].12.w)||0,C=6.f.C,F={1c:[],1j:[]};y(7 i=0;i<19;++i){7 c=6.L[0].G[i],1p=[];F.1c.R($(c));y(7 j=0;j<2r;++j){1p.R(C[j].H(1Q(6.f,c.12[j]),6,c.12[j]))}1p.R(i);F.1j.R(1p);1p=1E};q(6.f.J){17("2W F y "+19+" G:",23)}m F};8 1Q(f,V){q(!V)m"";7 t="";q(f.1w=="25"){q(V.1L[0]&&V.1L[0].2X()){t=V.1L[0].1S}N{t=V.1S}}N{q(1u(f.1w)=="8"){t=f.1w(V)}N{t=$(V).1i()}}m t}8 1G(6,F){q(6.f.J){7 2U=D T()}7 c=F,r=c.1c,n=c.1j,19=n.w,1J=(n[0].w-1),2h=$(6.L[0]),G=[];y(7 i=0;i<19;i++){G.R(r[n[i][1J]]);q(!6.f.20){7 o=r[n[i][1J]];7 l=o.w;y(7 j=0;j<l;j++){2h[0].32(o[j])}}}q(6.f.20){6.f.20(6,G)}G=1E;q(6.f.J){17("4d 6:",2U)}1z(6)};8 2x(6){q(6.f.J){7 1f=D T()}7 1o=($.1o)?13:K,27=[];y(7 i=0;i<6.1t.G.w;i++){27[i]=0};$1r=$("35 37",6);$1r.1s(8(1F){k.1a=0;k.1D=1F;k.18=2B(6.f.2P);q(2d(k)||2e(6,1F))k.1C=13;q(!k.1C){$(k).1q(6.f.28)}6.f.1y[1F]=k});q(6.f.J){17("3a x:",1f);1h($1r)}m $1r};8 2K(6,G,1c){7 1k=[],r=6.1t.G,c=r[1c].12;y(7 i=0;i<c.w;i++){7 11=c[i];q(11.41>1){1k=1k.3b(2K(6,3c,1c++))}N{q(6.1t.w==1||(11.3e>1||!r[1c+1])){1k.R(11)}}}m 1k};8 2d(11){q(($.1o)&&($(11).16().1g===K)){m 13};m K}8 2e(6,i){q((6.f.x[i])&&(6.f.x[i].1g===K)){m 13};m K}8 1z(6){7 c=6.f.1d;7 l=c.w;y(7 i=0;i<l;i++){1Z(c[i]).H(6)}}8 1Z(1x){7 l=1d.w;y(7 i=0;i<l;i++){q(1d[i].B.14()==1x.14()){m 1d[i]}}};8 2B(v){q(1u(v)!="3i"){i=(v.14()=="3j")?1:0}N{i=(v==(0||1))?v:0}m i}8 2E(v,a){7 l=a.w;y(7 i=0;i<l;i++){q(a[i][0]==v){m 13}}m K}8 1W(6,$x,Z,S){$x.1H(S[0]).1H(S[1]);7 h=[];$x.1s(8(3L){q(!k.1C){h[k.1D]=$(k)}});7 l=Z.w;y(7 i=0;i<l;i++){h[Z[i][0]].1q(S[Z[i][1]])}}8 2z(6,$x){7 c=6.f;q(c.2u){7 1v=$(\'<1v>\');$("2j:3l 3H",6.L[0]).1s(8(){1v.3G($(\'<3o>\').S(\'2l\',$(k).2l()))});$(6).3r(1v)}}8 2M(6,u){7 c=6.f,l=u.w;y(7 i=0;i<l;i++){7 s=u[i],o=c.1y[s[0]];o.1a=s[1];o.1a++}}8 1Y(6,u,F){q(6.f.J){7 2m=D T()}7 Y="7 2k = 8(a,b) {",l=u.w;y(7 i=0;i<l;i++){7 c=u[i][0];7 18=u[i][1];7 s=(2s(6.f.C,c)=="1i")?((18==0)?"2n":"2o"):((18==0)?"2p":"2q");7 e="e"+i;Y+="7 "+e+" = "+s+"(a["+c+"],b["+c+"]); ";Y+="q("+e+") { m "+e+"; } ";Y+="N { "}7 1N=F.1j[0].w-1;Y+="m a["+1N+"]-b["+1N+"];";y(7 i=0;i<l;i++){Y+="}; "}Y+="m 0; ";Y+="}; ";3t(Y);F.1j.3u(2k);q(6.f.J){17("3w 3x "+u.3z()+" 3A 3B "+18+" 1f:",2m)}m F};8 2n(a,b){m((a<b)?-1:((a>b)?1:0))};8 2o(a,b){m((b<a)?-1:((b>a)?1:0))};8 2p(a,b){m a-b};8 2q(a,b){m b-a};8 2s(C,i){m C[i].Q};k.2f=8(2w){m k.1s(8(){q(!k.1t||!k.L)m;7 $k,$3E,$x,F,f,3F=0,3I;k.f={};f=$.1V(k.f,$.I.2v,2w);$k=$(k);$x=2x(k);k.f.C=1T(k,$x);F=1U(k);7 1X=[f.29,f.2b];2z(k);$x.3K(8(e){7 19=($k[0].L[0]&&$k[0].L[0].G.w)||0;q(!k.1C&&19>0){7 $11=$(k);7 i=k.1D;k.18=k.1a++%2;q(!e[f.2D]){f.u=[];q(f.1I!=1E){7 a=f.1I;y(7 j=0;j<a.w;j++){f.u.R(a[j])}}f.u.R([i,k.18])}N{q(2E(i,f.u)){y(7 j=0;j<f.u.w;j++){7 s=f.u[j],o=f.1y[s[0]];q(s[0]==i){o.1a=s[1];o.1a++;s[1]=o.1a%2}}}N{f.u.R([i,k.18])}};$k.1R("3S");1W($k[0],$x,f.u,1X);3T(8(){1G($k[0],1Y($k[0],f.u,F));$k.1R("3U")},0);m K}}).3V(8(){q(f.2Q){k.3X=8(){m K};m K}});$k.1n("3Y",8(){k.f.C=1T(k,$x);F=1U(k)}).1n("2J",8(e,Z){f.u=Z;7 u=f.u;2M(k,u);1W(k,$x,u,1X);1G(k,1Y(k,u,F))}).1n("44",8(){1G(k,F)}).1n("45",8(e,B){1Z(B).H(k)}).1n("47",8(){1z(k)});q($.1o&&($(k).16()&&$(k).16().2N)){f.u=$(k).16().2N}q(f.u.w>0){$k.1R("2J",[f.u])}1z(k)})};k.P=8(1B){7 l=C.w,a=13;y(7 i=0;i<l;i++){q(C[i].B.14()==1B.B.14()){a=K}}q(a){C.R(1B)}};k.2R=8(21){1d.R(21)};k.U=8(s){7 i=2Y(s);m(26(i))?0:i};k.2Z=8(s){7 i=30(s);m(26(i))?0:i};k.33=8(6){q($.34.36){8 2I(){38(k.2a)k.39(k.2a)}2I.3d(6.L[0])}N{6.L[0].1S=""}}}});$.3f.1V({I:$.I.2f});7 M=$.I;M.P({B:"1i",O:8(s){m 13},H:8(s){m $.1M(s.14())},Q:"1i"});M.P({B:"3k",O:8(s){m/^\\d+$/.15(s)},H:8(s){m $.I.U(s)},Q:"W"});M.P({B:"3m",O:8(s){m/^[3n£$3p\82¬?.]/.15(s)},H:8(s){m $.I.U(s.X(D 1b(/[^0-9.]/g),""))},Q:"W"});M.P({B:"3s",O:8(s){m s.2G(D 1b(/^(\\+|-)?[0-9]+\\.[0-9]+((E|e)(\\+|-)?[0-9]+)?$/))},H:8(s){m $.I.U(s.X(D 1b(/,/),""))},Q:"W"});M.P({B:"3v",O:8(s){m/^\\d{2,3}[\\.]\\d{2,3}[\\.]\\d{2,3}[\\.]\\d{2,3}$/.15(s)},H:8(s){7 a=s.3y("."),r="",l=a.w;y(7 i=0;i<l;i++){7 1A=a[i];q(1A.w==2){r+="0"+1A}N{r+=1A}}m $.I.U(r)},Q:"W"});M.P({B:"3J",O:8(s){m/^(2y?|2A|2C):\\/\\/$/.15(s)},H:8(s){m 2T.1M(s.X(D 1b(/(2y?|2A|2C):\\/\\//),\'\'))},Q:"1i"});M.P({B:"3P",O:8(s){m/^\\d{4}[\\/-]\\d{1,2}[\\/-]\\d{1,2}$/.15(s)},H:8(s){m $.I.U((s!="")?D T(s.X(D 1b(/-/g),"/")).1e():"0")},Q:"W"});M.P({B:"3Q",O:8(s){m/^\\d{1,3}%$/.15(s)},H:8(s){m $.I.U(s.X(D 1b(/%/g),""))},Q:"W"});M.P({B:"3R",O:8(s){m s.2G(D 1b(/^[A-3W-z]{3,10}\\.? [0-9]{1,2}, ([0-9]{4}|\'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\\s(40|42)))$/))},H:8(s){m $.I.U(D T(s).1e())},Q:"W"});M.P({B:"43",O:8(s){m/\\d{1,2}[\\/\\-]\\d{1,2}[\\/\\-]\\d{2,4}/.15(s)},H:8(s,6){7 c=6.f;s=s.X(/\\-/g,"/");q(c.1l=="2O"){s=s.X(/(\\d{1,2})[\\/\\-](\\d{1,2})[\\/\\-](\\d{4})/,"$3/$1/$2")}N q(c.1l=="46"){s=s.X(/(\\d{1,2})[\\/\\-](\\d{1,2})[\\/\\-](\\d{4})/,"$3/$2/$1")}N q(c.1l=="2t/24/2g"||c.1l=="2t-24-2g"){s=s.X(/(\\d{1,2})[\\/\\-](\\d{1,2})[\\/\\-](\\d{2})/,"$1/$2/$3")}m $.I.U(D T(s).1e())},Q:"W"});M.P({B:"1f",O:8(s){m/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\\s(3g|3h)))$/.15(s)},H:8(s){m $.I.U(D T("3q/2i/2i "+s).1e())},Q:"W"});M.P({B:"3D",O:8(s){m K},H:8(s,6,11){7 c=6.f,p=(!c.2F)?\'3M\':c.2F;m $(11).16()[p]},Q:"W"});M.2R({B:"31",H:8(6){q(6.f.J){7 1f=D T()}$("2j:3C",6.L[0]).2H(\':2c\').1H(6.f.1m.S[1]).1q(6.f.1m.S[0]).3O().2H(\':2L\').1H(6.f.1m.S[0]).1q(6.f.1m.S[1]);q(6.f.J){$.I.17("3N 4e 21",1f)}}})})(2T);',62,263,'||||||table|var|function|||||||config|||||this||return||||if||||sortList||length|headers|for|||id|parsers|new||cache|rows|format|tablesorter|debug|false|tBodies|ts|else|is|addParser|type|push|css|Date|formatFloat|node|numeric|replace|dynamicExp|list||cell|cells|true|toLowerCase|test|data|benchmark|order|totalRows|count|RegExp|row|widgets|getTime|time|sorter|log|text|normalized|arr|dateFormat|widgetZebra|bind|meta|cols|addClass|tableHeaders|each|tHead|typeof|colgroup|textExtraction|name|headerList|applyWidget|item|parser|sortDisabled|column|null|index|appendToTable|removeClass|sortForce|checkCell|getParserById|childNodes|trim|orgOrderCol|parsersDebug|console|getElementText|trigger|innerHTML|buildParserCache|buildCache|extend|setHeadersCss|sortCSS|multisort|getWidgetById|appender|widget|detectParserForColumn|cacheTime|mm|simple|isNaN|tableHeadersRows|cssHeader|cssDesc|firstChild|cssAsc|even|checkHeaderMetadata|checkHeaderOptions|construct|yy|tableBody|01|tr|sortWrapper|width|sortTime|sortText|sortTextDesc|sortNumeric|sortNumericDesc|totalCells|getCachedSortType|dd|widthFixed|defaults|settings|buildHeaders|https|fixColumnWidth|ftp|formatSortingOrder|file|sortMultiSortKey|isValueInArray|parserMetadataName|match|filter|empty|sorton|checkCellColSpan|odd|updateHeaderSortCount|sortlist|us|sortInitialOrder|cancelSelection|addWidget|undefined|jQuery|appendTime|alert|Building|hasChildNodes|parseFloat|formatInt|parseInt|zebra|appendChild|clearTableBody|browser|thead|msie|th|while|removeChild|Built|concat|headerArr|apply|rowSpan|fn|am|pm|Number|desc|integer|first|currency|Â|col|â|2000|prepend|floating|eval|sort|ipAddress|Sorting|on|split|toString|and|dir|visible|metadata|document|shiftDown|append|td|sortOrder|url|click|offset|sortValue|Applying|end|isoDate|percent|usLongDate|sortStart|setTimeout|sortEnd|mousedown|Za|onselectstart|update|header|AM|colSpan|PM|shortDate|appendCache|applyWidgetId|uk|applyWidgets|headerSortUp|headerSortDown|asc|shiftKey|ms|Rebuilt|Zebra'.split('|'),0,{}))
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/kaejax_replaces.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/kaejax_replaces.js
new file mode 100644 (file)
index 0000000..3d69301
--- /dev/null
@@ -0,0 +1,26 @@
+// see license.txt for licensing
+var kfm_kaejax_replaces={'([89A-F][A-Z0-9])':'%u00$1','22':'"','2C':',','3A':':','5B':'[','5D':']','7B':'{','7D':'}'};
+if(window.ie){
+       window.kfm_kaejax_replaces_regexps=[];
+       window.kfm_kaejax_replaces_replacements=[];
+       for(var i in kfm_kaejax_replaces){
+               kfm_kaejax_replaces_regexps.push(eval('/%'+i+'/g'));
+               kfm_kaejax_replaces_replacements.push(kfm_kaejax_replaces[i]);
+       }
+}
+else{
+       for(var a in kfm_kaejax_replaces){
+               kfm_kaejax_replaces[kfm_kaejax_replaces[a]]=eval('/%'+a+'/g');
+               delete kfm_kaejax_replaces[a];
+       }
+}
+var kfm_sanitise_ajax=window.ie?
+       function(d){
+               for(var a in window.kfm_kaejax_replaces_regexps)d=d.replace(kfm_kaejax_replaces_regexps[a],kfm_kaejax_replaces_replacements[a]);
+               return d;
+       }:
+       function(d){
+               var r=kfm_kaejax_replaces;
+               for(var a in r)d=d.replace(r[a],a);
+               return d;
+       };
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/kdnd.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/kdnd.js
new file mode 100644 (file)
index 0000000..8d72dcb
--- /dev/null
@@ -0,0 +1,124 @@
+function kdnd_addDropHandler(source_class,target_selector,func){
+       if(!kdnd_targets[source_class])kdnd_targets[source_class]={};
+       kdnd_targets[source_class][target_selector]=func;
+}
+function kdnd_makeDraggable(source_class){
+       if($type(source_class)=='array'){
+               return source_class.each(kdnd_makeDraggable);
+       }
+       var els=$ES('.'+source_class),i,el;
+       els.each(function(el){
+               if(el.kdnd_applied)return;
+               el.kdnd_applied=true;
+               if(!el.dragevents)el.dragevents=[];
+               if(!el.dragevents[source_class])el.dragevents[source_class]=kdnd_dragInit(el,source_class);
+               el.addEvent('mousedown',el.dragevents[source_class]);
+       });
+}
+function kdnd_unmakeDraggable(source_class){
+       if($type(source_class)=='array'){
+               return source_class.each(kdnd_unmakeDraggable);
+       }
+       var els=$$('.'+source_class),i,el;
+       for(i=0;i<els.length;++i){
+               el=els[i];
+               if(!el.kdnd_applied)continue;
+               el.kdnd_applied=false;
+               if(!el.dragevents)el.dragevents=[];
+               if(!el.dragevents[source_class])el.dragevents[source_class]=kdnd_dragInit(el,source_class);
+               el.removeEvent('mousedown',el.dragevents[source_class]);
+       }
+}
+function kdnd_drag(e){
+       e=new Event(e);
+       if(!window.kdnd_dragging)return;
+       var m=e.page;
+       clearSelections();
+       window.kdnd_drag_wrapper.setStyles({
+               'position':'absolute',
+               'display':'block',
+               'left':(m.x+window.kdnd_offset.x),
+               'top':(m.y+window.kdnd_offset.y)
+       });
+       if(kdnd_source_el.hasClass('drag_this')){
+               kdnd_source_el.setStyle('visibility','hidden');
+       }
+}
+function kdnd_dragFinish(e,notest){
+       e=new Event(e);
+       clearTimeout(window.dragTrigger);
+       if(!window.kdnd_dragging)return;
+       if(!notest){ // check for targets and run functions if found
+               var a,b,t=$H(kdnd_targets[window.kdnd_drag_class]),els,m=e.page,el;
+               t.each(function(fn,a){
+                       els=$ES(a);
+                       for(b=0;b<els.length;++b){
+                               el=els[b];
+                               if(getOffset(el,'Left')<=m.x&&m.x<getOffset(el,'Left')+el.offsetWidth&&getOffset(el,'Top')<=m.y&&m.y<getOffset(el,'Top')+el.offsetHeight){
+                                       e=$extend(e,{
+                                               'sourceElement':kdnd_source_el,
+                                               'targetElement':el
+                                       });
+                                       fn(e);
+                               }
+                       }
+               });
+               if(kdnd_source_el.hasClass('drag_this')){
+                       kdnd_source_el.setStyles({
+                               'left'       : (m.x+window.kdnd_offset.x),
+                               'top'        : (m.y+window.kdnd_offset.y),
+                               'visibility' : 'visible'
+                       });
+               }
+       }
+       { // cleanup
+               window.kdnd_dragging=false;
+               document.removeEvent('mousemove',kdnd_drag);
+               document.removeEvent('mouseup',kdnd_dragFinish);
+               window.kdnd_drag_wrapper.remove();
+               window.kdnd_drag_wrapper=null;
+               window.kdnd_source_el=null;
+       }
+}
+function kdnd_dragInit(el,source_class){
+       return function(e){
+               e=new Event(e);
+               if(e.rightClick)return;
+               document.addEvent('mouseup',kdnd_dragFinish);
+               clearTimeout(window.dragTrigger);
+               window.dragTrigger=setTimeout(function(){
+                       kdnd_dragStart(el,source_class);
+               },100);
+               window.kdnd_offset={'x':el.offsetLeft-e.page.x,'y':el.offsetTop-e.page.y};
+               e.stop();
+       };
+}
+function kdnd_dragStart(el,source_class){
+       window.kdnd_dragging=true;
+       window.kdnd_drag_class=source_class;
+       window.kdnd_source_el=el;
+       var content=el.dragDisplay?el.dragDisplay():el.cloneNode(true);
+       if(el.getStyle('position')=='absolute' || el.getStyle('position')=='fixed')content.setStyles({
+               'position' : 'static',
+               'left'     : 0,
+               'top'      : 0
+       });
+       if(!el.hasClass('drag_this'))window.kdnd_offset={'x':16,'y':0};
+       var styles=window.ie?{
+               'display':'none'
+       }:
+       {
+               'display':'none',
+               'opacity':.7
+       };
+       window.kdnd_drag_wrapper=new Element('div',{
+               'id':'kdnd_drag_wrapper',
+               'styles':styles
+       });
+       window.kdnd_drag_wrapper.appendChild(content);
+       document.body.appendChild(window.kdnd_drag_wrapper);
+       document.addEvent('mousemove',kdnd_drag);
+}
+{ // variables
+       var kdnd_targets=[];
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/kfm.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/kfm.js
new file mode 100644 (file)
index 0000000..bf24adb
--- /dev/null
@@ -0,0 +1,528 @@
+// see license.txt for licensing
+var KFM=new Class({
+       about:function(){
+               var div=new Element('div',{
+                       'styles':{
+                               'width':400
+                       }
+               });
+               var html='<h1>KFM '+kfm_vars.version+'</h1>';
+               { // sponsors
+                       html+='<h2>Sponsors</h2>';
+                       html+='KFM is free software. Here are some recent sponsors:<br />';
+                       html+='<a href="http://tinyurl.com/2uerfm" style="float:right;display:block;border:1px solid red;background:#fff;text-decoration:none;text-align:center;margin-right:10px" target="_blank">Donate to KFM</a>';
+                       html+='<a href="http://webworks.ie/" target="_blank"><strong>webworks.ie</strong></a><br />';
+                       html+='<a href="http://www.bluenectar.com.au/" target="_blank">Blue Nectar</a><br />';
+               }
+               { // developers
+                       html+='<h2>Developers</h2>';
+                       html+='<a href="http://verens.com/" target="_blank"><strong>Kae Verens</strong></a><br />';
+                       html+='<a href="http://www.companytools.nl/kfm" target="_blank">Benjamin ter Kuile</a><br />';
+               }
+               { // translators
+                       html+='<h2>Translators</h2><table><tr><td>';
+                       html+='bg (Bulgarian): Tondy<br />';
+                       html+='cz (Czech): Petr Kamenik<br />';
+                       html+='da (Danish): Janich Rasmussen<br />';
+                       html+='de (German): Just Agens<br />';
+                       html+='en (English): Kae Verens<br />';
+                       html+='es (Spanish): Ramón Ramos<br />';
+                       html+='fa (Persion/Farsi): Ghassem Tofighi<br />';
+                       html+='fi (Finnish): Hannu (hlpilot)</td><td>';
+                       html+='fr (French): Hubert Garrido<br />';
+                       html+='ga (Irish): Kae Verens<br />';
+                       html+='hu (Hungarian): Ujj-Mészáros István<br />';
+                       html+='it (Italian): Stefano Luchetta<br />';
+                       html+='nl (Dutch): Roy Lubbers<br />';
+                       html+='pl (Polish): Jan Kurek<br />';
+                       html+='ro (Romanian): Andrei Suscov<br />';
+                       html+='ru (Russian): Andrei Suscov<br />';
+                       html+='sv (Swedish): Aram Mäkivierikko</td></tr></table>';
+               }
+               { // bug testers
+                       html+='<h2>Bug Testers</h2>';
+                       html+='To many to mention! To report a bug, please <a href="http://mantis.verens.com/">go here</a>.';
+               }
+               div.setHTML(html);
+               //kfm_modal_open(div,kfm.lang.AboutKfm);
+        kfm_modal_open(div,"File Manager");
+       },
+       addCell:function(o,colNum,colSpan,subEls,className){
+               var f=$(o.insertCell(+colNum));
+               if(colSpan)f.colSpan=colSpan;
+               if(subEls)kfm.addEl(f,subEls);
+               if(className)f.className=className;
+               return f;
+       },
+       addEl:function(o,a){
+               if(!o)return;
+               if(!a)return o;
+               if($type(a)!='array')a=[a];
+               for(var i=0;i<a.length;++i){
+                       if($type(a[i])=='array'){
+                               kfm.addEl(o,a[i]);
+                       }
+                       else{
+                               if($type(a[i])=='string')a[i]=newText(a[i]);
+                               if(!a[i])return;
+                               o.appendChild(a[i]);
+                       }
+               }
+               return o;
+       },
+       addRow:function(t,p,c){
+               var o=t.insertRow(p===parseInt(p)?p:t.rows.length);
+               if(c && c!=undefined)o.className=c;
+               return o;
+       },
+       alert:function(txt){
+               window.inPrompt=1;
+               alert(txt);
+               setTimeout('window.inPrompt=0',1);
+       },
+       showErrors:function(errors){
+               var div=new Element('div',{
+                       'styles':{
+                               'width':400
+                       }
+               });
+               var html='';
+               for(var i=0;i<errors.length;i++){
+                       html+='<span>'+errors[i].message+'</span><br/>';
+                       /* Add tooltip or do something with:
+                        *errors[i].level
+                        *errors[i].function
+                        *errors[i].class
+                        *errors[i].file
+                        */
+               }
+               div.setHTML(html);
+               kfm_modal_open(div,kfm.lang.Errors);
+       },
+       showMessages:function(messages){
+               var message='';
+               for(var i=0;i<messages.length;i++){
+                       message+=messages[i].message+'<hr>';
+               }
+               new Notice(message);
+       },
+       switchFilesMode:function(m){
+               kfm_listview = +m;
+               x_kfm_loadFiles(kfm_cwd_id,true,kfm_refreshFiles);
+       },
+       build:function(){
+               kfm_addHook({name:"download", mode:0,"extensions":"all", writable:2, title:"download file", doFunction:function(files){
+                               kfm_downloadSelectedFiles(files[0]);
+                       }
+               });
+               if(!window.ie)kfm_addHook({name:"download", mode:1,"extensions":"all", writable:2, title:"download selected files", doFunction:function(files){
+                               kfm_downloadSelectedFiles();
+                       }
+               });
+               if(kfm_vars.permissions.file.rm)kfm_addHook({name:"remove", mode:2,extensions:"all", writable:1,title:kfm.lang.DeleteFile, doFunction:function(files){
+                               if(files.length>1)kfm_deleteSelectedFiles();
+                               else kfm_deleteFile(files[0]);
+                       }
+               });
+               if(kfm_vars.permissions.file.ed)kfm_addHook({name:"rename", mode:0,extensions:"all", writable:1,title:kfm.lang.RenameFile, doFunction:function(files){
+                               kfm_renameFile(files[0]);
+                       }
+               });
+               var form_panel,form,right_column,directories,logs,logHeight=64,w=window.getSize().size,j,i;
+               { // extend language objects
+                       for(var j in kfm.lang){
+                               if(kfm_regexps.percent_numbers.test(kfm.lang[j])){
+                                       kfm.lang[j]=(function(str){
+                                               return function(){
+                                                       var tmp=str;
+                                                       for(i=1;i<arguments.length+1;++i)tmp=tmp.replace("%"+i,arguments[i-1]);
+                                                       return tmp;
+                                               };
+                                       })(kfm.lang[j]);
+                               }
+                       }
+               }
+               kfm_cwd_name=starttype;
+               $(document.body).setStyle('overflow','hidden');
+               $('removeme').remove();
+               /*
+               kfm_addContextMenu(document.body,function(e){
+                       var links=[['kfm.about()',kfm.lang.AboutKfm]];
+                       var links=[{title:kfm.lang.AboutKfm, doFunction:function(){kfm.about();}}];
+                       var links=[];
+                       kfm_createContextMenu(e.page,links);
+               });
+               */
+               if(kfm_vars.use_templates){
+                       $('templateWrapper').style.display='block';
+                       var documents_body=$('documents_body');
+                       if(!documents_body)alert('no #documents_body on page - please fix your template');
+                       var wrapper=$('kfm_search_wrapper');
+                       if(wrapper)wrapper.appendChild(kfm_searchBoxFile());
+                       var wrapper=$('kfm_upload_wrapper');
+                       if(wrapper)kfm.addEl(wrapper,kfm_createFileUploadPanel(true));
+               }
+               else{
+                       { // create left column
+                               var left_column=kfm_createPanelWrapper('kfm_left_column');
+                               kfm_resizeHandler_addMaxHeight('kfm_left_column');
+                               kfm_addPanel(left_column,'kfm_directories_panel');
+                               //kfm_addPanel(left_column,'kfm_widgets_panel');
+                               kfm_addPanel(left_column,'kfm_search_panel');
+                               //kfm_addPanel(left_column,'kfm_directory_properties_panel');
+                               if(!kfm_inArray('kfm_logs_panel',kfm_hidden_panels))kfm_addPanel(left_column,'kfm_logs_panel');
+                               left_column.panels_unlocked=1;
+                               left_column.setStyles('height:'+w.y+'px');
+                               kfm_addContextMenu(left_column,function(e){
+                                       var links=[],i;
+                                       var l=left_column.panels_unlocked;
+                                       links.push({title:l?'lock':'unlock', doFunction:function(){
+                                                       kfm_togglePanelsUnlocked();
+                                               }
+                                       });
+                                       var ps=left_column.panels;
+                                       for(var i=0;i<ps.length;++i){
+                                               var p=$(ps[i]);
+                                               if(!p.visible && !kfm_inArray(ps[i],kfm_hidden_panels))links.push({title:'Show panel '+p.panel_title, doFunction:function(){
+                                                               kfm_addPanel("kfm_left_column",ps[i]);
+                                                       }
+                                               });
+                                       }
+                                       kfm_createContextMenu(e.page,links);
+                               });
+                       }
+                       { // create right_column
+                               right_column=new Element('div',{
+                                       'id':'kfm_right_column'
+                               });
+                          var lselect=new Element('select',{   
+                              'styles':{
+                                  'position':'absolute',
+                                  'z-index':2,
+                                  'right':0,
+                                  'top':1,
+                                  'border':0
+                              },
+                              'events':{
+                                  'change':function(){
+                                                                               kfm.switchFilesMode(this.value);
+                                  }
+                              }
+                          });
+                          lselect.appendChild((new Element('option',{
+                              'selected':!kfm_listview,
+                              'value':0
+                          })).appendText(kfm.lang.Icons));
+                          lselect.appendChild((new Element('option',{
+                              'selected':kfm_listview,
+                              'value':1
+                          })).appendText(kfm.lang.ListView));
+
+                          var header=new Element('div',{
+                              'class':'kfm_panel_header',
+                              'id':'kfm_panel_header'
+                          }).setHTML('<span id="documents_loader"></span><span id="cwd_display"></span><span id="folder_info"></span>');
+
+                               var documents_body=new Element('div',{
+                                       'id':'documents_body'
+                               });
+                         right_column.appendChild(lselect);
+                         right_column.appendChild(header);
+                               right_column.appendChild(documents_body);
+                       }
+                       { // draw areas to screen and load files and directory info
+                               document.body.appendChild(left_column);
+                               document.body.appendChild(right_column);
+                       }
+               }
+               { // set up main panel
+                       documents_body.addEvent('click',function(e){
+                               e=new Event(e);
+                               if(e.rightClick)return;
+                               if(!window.dragType)kfm_selectNone()
+                       });
+                       documents_body.addEvent('mousedown',function(e){
+                               e=new Event(e);
+                               if(e.rightClick)return;
+                               window.mouseAt=e.page;
+                               if(this.contentMode=='file_icons' && this.fileids.length)window.dragSelectionTrigger=setTimeout(function(){kfm_selection_dragStart()},200);
+                               documents_body.addEvent('mouseup',kfm_selection_dragFinish);
+                       });
+                       kfm_addContextMenu(documents_body,function(e){
+                               var links=[],i;
+                               links.push(['kfm_createEmptyFile()',kfm.lang.CreateEmptyFile,'filenew',!kfm_vars.permissions.file.mk]);
+                               if(selectedFiles.length>1)links.push(['kfm_renameFiles()',kfm.lang.RenameFile,'edit',!kfm_vars.permissions.file.ed]);
+                               if(selectedFiles.length>1)links.push(['kfm_zip()',kfm.lang.ZipUpFiles,'',!kfm_vars.permissions.file.mk]);
+                               if(selectedFiles.length!=$('documents_body').fileids.length)links.push(['kfm_selectAll()',kfm.lang.SelectAll,'ark_selectall']);
+                               if(selectedFiles.length){ // select none, invert selection
+                                       links.push(['kfm_selectNone()',kfm.lang.SelectNone,'select_none']);
+                                       links.push(['kfm_selectInvert()',kfm.lang.InvertSelection,'invert_selection']);
+                               }
+                               kfm_createContextMenu(e.page,links);
+                       });
+                       documents_body.parentResized=kfm_files_reflowIcons;
+               }
+               var dirs=$('kfm_directories');
+               if(dirs){
+                       x_kfm_loadDirectories(kfm_vars.root_folder_id,kfm_refreshDirectories);
+                       kfm_addContextMenu(dirs.parentNode,function(e){
+                               var links=[];
+                               links.push(['kfm_createDirectory(1)',kfm.lang.CreateSubDir,'folder_new',!kfm_vars.permissions.dir.mk]);
+                               if(kfm_return_directory)links.push(['setTimeout("window.close()",1);window.opener.SetUrl("'+kfm_directories[node_id].realpath+'/");',kfm.lang.SendToCms]);
+                               if(!window.contextmenu){
+                                       e=new Event(e);
+                                       kfm_createContextMenu(e.page,links);
+                               }
+                       });
+               }
+// testtest
+               x_kfm_loadFiles(kfm_vars.startupfolder_id,kfm_refreshFiles);
+               document.addEvent('keyup',kfm.keyup);
+               window.addEvent('resize',kfm_resizeHandler);
+               kfm_contextmenuinit();
+       },
+       confirm:function(txt){
+               window.inPrompt=1;
+               var ret=confirm(txt);
+               setTimeout('window.inPrompt=0',1);
+               return ret;
+       },
+       getContainer:function(p,c){
+               for(var i=0;i<c.length;++i){
+                       var a=c[i],x=getOffset(a,'Left'),y=getOffset(a,'Top');
+                       if(x<p.x&&y<p.y&&x+a.offsetWidth>p.x&&y+a.offsetHeight>p.y)return a;
+               }
+       },
+       getParentEl:function(c,t){
+               while(c.tagName!=t&&c)c=c.parentNode;
+               return c;
+       },
+       initialize:function(){
+               document.addEvent('domready',this.build);
+       },
+       keyup:function(e){
+               var e=new Event(e);
+               var key=e.code;
+               var cm=$('documents_body').contentMode;
+               switch(key){
+                       case 8:{ // delete
+                               kfm_delete(cm);
+                               break;
+                       }
+                       case 13:{ // enter
+                               if(!selectedFiles.length||window.inPrompt||cm!='file_icons')return;
+                               kfm_chooseFile();
+                               break;
+                       }
+                       case 27:{ // escape
+                               if(cm=='lightbox')kfm_img_stopLightbox();
+                               else if(!window.inPrompt&&kfm.confirm(kfm.lang.AreYouSureYouWantToCloseKFM))window.close();
+                               break;
+                       }
+                       case 37:{ // left arrow
+                               if(cm=='file_icons'){
+                                       if(!kfm_listview)kfm_shiftFileSelectionLR(-1);
+                               }
+                               else if(cm=='lightbox'){
+                                       window.kfm_slideshow_stopped=1;
+                                       if(window.lightbox_slideshowTimer)clearTimeout(window.lightbox_slideshowTimer);
+                                       window.kfm_slideshow.at-=2;
+                                       kfm_img_startLightbox();
+                               }
+                               else break;
+                               e.stopPropagation();
+                               break;
+                       }
+                       case 38:{ // up arrow
+                               if(cm=='file_icons'){
+                                       if(kfm_listview)kfm_shiftFileSelectionLR(-1);
+                                       else kfm_shiftFileSelectionUD(-1);
+                               }
+                               break;
+                       }
+                       case 39:{ // right arrow
+                               if(cm=='file_icons'){
+                                       if(!kfm_listview)kfm_shiftFileSelectionLR(1);
+                               }
+                               else if(cm=='lightbox'){
+                                       window.kfm_slideshow_stopped=1;
+                                       if(window.lightbox_slideshowTimer)clearTimeout(window.lightbox_slideshowTimer);
+                                       kfm_img_startLightbox();
+                               }
+                               else break;
+                               e.stopPropagation();
+                               break;
+                       }
+                       case 40:{ // down arrow
+                               if(cm=='file_icons'){
+                                       if(kfm_listview)kfm_shiftFileSelectionLR(1);
+                                       else kfm_shiftFileSelectionUD(1);
+                               }
+                               break;
+                       }
+                       case 46:{ // delete
+                               kfm_delete(cm);
+                               break;
+                       }
+                       case 65:{ // a
+                               if(e.control&&cm=='file_icons'){
+                                       clearSelections(e);
+                                       kfm_selectAll();
+                               }
+                               break;
+                       }
+                       case 85:{ // u
+                               if(e.control&&cm=='file_icons'){
+                                       clearSelections(e);
+                                       kfm_selectNone();
+                               }
+                               break;
+                       }
+                       case 113:{ // f2
+                               if(cm!='file_icons')return;
+                               if(!selectedFiles.length)return kfm.alert(kfm.lang.PleaseSelectFileBeforeRename);
+                               if(selectedFiles.length==1){
+                                       kfm_renameFile(selectedFiles[0]);
+                               }
+                               else kfm.alert(kfm.lang.RenameOnlyOneFile);
+                               break;
+                       }
+                       case 127:{ // backspace
+                               kfm_delete(cm);
+                               break;
+                       }
+               }
+       }
+});
+function kfm_delete(cm){
+       if(!selectedFiles.length||cm!='file_icons')return;
+       if(selectedFiles.length>1)kfm_deleteSelectedFiles();
+       else kfm_deleteFile(selectedFiles[0]);
+}
+function kfm_inArray(needle,haystack){
+       for(var i=0;i<haystack.length;++i)if(haystack[i]==needle)return true;
+       return false;
+}
+function kfm_log(msg){
+       var wrapper=$('kfm_logs_panel');
+       if(!wrapper){
+               if(msg.indexOf(kfm.lang.ErrorPrefix)!=0 && msg.indexOf('error: ')!=0)return;
+               if(kfm_inArray('kfm_logs_panel',kfm_hidden_panels))return kfm.alert(msg.replace(kfm.lang.ErrorPrefix,'').replace('error: ',''));
+               kfm_addPanel('kfm_left_column','kfm_logs_panel');
+               kfm_refreshPanels('kfm_left_column');
+               wrapper=$('kfm_logs_panel');
+       }
+       wrapper.visible=1;
+       var el=$E('#kfm_logs_panel div.kfm_panel_body'),p=(new Element('p')).setHTML(msg);
+       if(msg.indexOf(kfm.lang.ErrorPrefix)==0)p.setStyles('background:#ff0;fontWeight:bold;color:red');
+       kfm.addEl(el,p);
+       el.scrollTop=el.scrollTop+p.offsetHeight;
+}
+function kfm_prompt(txt,val,fn){
+       window.inPrompt=1;
+       var table=new Element('table',{
+               'id':'kfm_prompt_table'
+       });
+       var row=table.insertRow(0),inp=newInput('kfm_prompt',0,val);
+       row.insertCell(0).innerHTML=txt.replace(/\n/g,'<br />');
+       row.insertCell(1).appendChild(inp);
+       kfm_modal_open(table,'prompt',[[kfm.lang.Ok,function(){
+               var v=$('kfm_prompt').value;
+               kfm_modal_close();
+               window.inPrompt=0;
+               fn(v);
+       }]]);
+       $('kfm_prompt').focus();
+}
+function kfm_run_delayed(name,call){
+       name=name+'_timeout';
+       if(window[name])$clear(window[name]);
+       window[name]=setTimeout(call,500);
+}
+function kfm_shrinkName(name,wrapper,text,size,maxsize,extension){
+       var position=step=Math.ceil(name.length/2),postfix='[...]'+extension,prefix=size=='offsetHeight'?'. ':'';
+       do{
+               text.innerHTML=prefix+name.substring(0,position)+postfix;
+               step=Math.ceil(step/2);
+               position+=(wrapper[size]>maxsize)?-step:step;
+       }while(step>1);
+       //var html='<span class="filename">'+name.substring(0,position+(prefix?0:-1))+'</span><span style="color:red;text-decoration:none">[...]</span>';
+    var html='<span class="filename">'+name.substring(0,10)+'</span><span style="color:red;text-decoration:none">[...]</span>';
+       if(extension)html+='<span class="filename">'+extension+'</span>';
+       text.innerHTML=html;
+}
+/* Start kfm plugin iframe functions */
+function kfm_pluginIframeShow(url){
+       if(url){
+               $j('#plugin_iframe_div').remove();
+               var jDiv=$j('<div id="plugin_iframe_div"></div>').css({
+                       'display':'none',
+                       'position':'absolute',
+                       'left':0,
+                       'top':0,
+                       'width':'100%',
+                       'height':'100%',
+                       'backgroundImage':'url(i/bg-black-75.png)',
+                       'z-index':202
+               });
+               $j(jDiv).appendTo('body');
+               $j(jDiv).append($j('<div id="plugin_iframe_header"></div>').css({
+                       'width':'100%',
+                       'height':'25px',
+                       'color':'white',
+                       'backgroundColor':'black'
+               }));
+               kfm_pluginIframeButton('close');
+               $j(jDiv).slideDown('normal',function(){
+                       var x=$j('body').width(),y=$j('body').height()-25;
+                       $j(this).append(
+                               '<iframe id="plugin_iframe_element" src="'+url+'&ifx='+x+'&ify='+y+'" style="width:100%;height:100%;"></iframe>'
+                       );
+               });
+       }else{
+               $j('#plugin_iframe_div').slideDown('normal');
+       }
+}
+function kfm_pluginIframeButton(code,text){
+       var btncode,btn;
+       var hdr=document.getElementById('plugin_iframe_header');
+       if(!hdr)return;
+       if(code=='close'){
+               btn=$j('<img src="themes/'+kfm_theme+'/icons/remove.png"/>').click(function(){kfm_pluginIframeHide();});
+               btn.css({'float':'right'});
+       }else{
+               btn=$j('<span class="kfm_plugin_iframe_button"></span>').click(function(){eval(code);});
+       }
+       if(text)$j(btn).text(text);
+       $j(btn).appendTo(hdr);
+}
+function kfm_pluginIframeHide(){
+       $j('#plugin_iframe_div').slideUp('normal');
+       //var ifd=document.getElementById('plugin_iframe_div');
+       //if(ifd) ifd.style.display='none';
+}
+function kfm_pluginIframeMessage(message){
+       /* not tested yet, should not be needed*/
+       var msgdiv=document.getElementById('plugin_iframe_message');
+       if(!msgdiv)return;
+       msgdiv.innerHTML=message;
+       msgdiv.style.display='block';
+       setTimeOut('document.getElementById("plugin_iframe_message").style.display="none";',3000);
+}
+function kfm_pluginIframeVar(varname){
+       var ifr=document.getElementById('plugin_iframe_element');
+       if(!ifr) return null;
+       var ifrvar=eval('ifr.contentWindow.'+varname);
+       return ifrvar;
+}
+/* End kfm plugin iframe functions */
+var kfm_regexps={
+       all_up_to_last_dot:/.*\./,
+       all_up_to_last_slash:/.*\//,
+       ascii_stuff:/%([89A-F][A-Z0-9])/g,
+       get_filename_extension:/.*\.([^.]*)$/,
+       percent_numbers:/%[1-9]/,
+       plus:/\+/g,
+       remove_filename_extension:/\.[^.]*$/
+}
+var kfm=new KFM();
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/modal.dialog.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/modal.dialog.js
new file mode 100755 (executable)
index 0000000..a244214
--- /dev/null
@@ -0,0 +1,111 @@
+function kfm_modal_close(msg){\r
+       $('shader').remove();\r
+       $('formWrapper').remove();\r
+       if(msg)alert(msg);\r
+}\r
+function kfm_modal_open(form,title,actions){\r
+       window.inPrompt=1;\r
+       var body=document.body,scrollAt=window.ie?getWindowScrollAt():{x:0,y:0},a=window.getSize().size,wx=0,wy=0,pos=window.ie?'absolute':'fixed',i;\r
+       if(window.ie)body.setStyles({\r
+               'overflow':'hidden'\r
+       });\r
+       { // shader\r
+               var shader=new Element('div',{\r
+                       'id':'shader',\r
+                       'styles':{\r
+                               'background':'#fff',\r
+                               'opacity':'.5',\r
+                               'position':pos,\r
+                               'top':scrollAt.y,\r
+                               'left':scrollAt.x,\r
+                               'z-index':2,\r
+                               'width':a.x,\r
+                               'height':a.y\r
+                       }\r
+               });\r
+               body.appendChild(shader);\r
+       }\r
+       { // wrapper\r
+               var wrapper=new Element('div',{\r
+                       'id'   :'formWrapper',\r
+                       'class':'modal_dialog drag_this'\r
+               });\r
+               var h2=(new Element('h2')).setHTML(title);\r
+               h2.className='prompt';\r
+               form.setStyles({\r
+                       'position':'relative',\r
+                       'margin':0,\r
+                       'text-align':'left',\r
+                       'padding':0,\r
+                       'clear':'left'\r
+               });\r
+               wrapper.appendChild(h2);\r
+               wrapper.appendChild(form);\r
+               { // link row\r
+                       var row=new Element('div');\r
+                       var link=new Element('a',{\r
+                               'href':'javascript:kfm_modal_close()'\r
+                       }).appendText(kfm.lang.Cancel);\r
+                       link.className='button';\r
+                       row.appendChild(link);\r
+                       if(actions&&actions.length)for(i=0;i<actions.length;++i){\r
+                               var v=actions[i];\r
+                               link=new Element('a',{\r
+                                       'href':'#',\r
+                                       'events':{\r
+                                               'click':v[1]\r
+                                       }\r
+                               }).appendText(v[0]);\r
+                               link.className='button';\r
+                               row.appendChild(link);\r
+                       }\r
+                       wrapper.appendChild(row);\r
+               }\r
+               row.setStyles({\r
+                       'background':'#eee',\r
+                       'border-top':'1px solid #ddd',\r
+                       'text-align':'right',\r
+                       'padding':'2px',\r
+                       'z-index':'3'\r
+               });\r
+               body.appendChild(wrapper);\r
+               wrapper.style.width=(form.offsetWidth+10)+'px';\r
+               var w=wrapper.offsetWidth;\r
+               if(w<200||w>a.x*.9){\r
+                       w=w<200?200:parseInt(a.x*.9);\r
+                       wrapper.setStyles({\r
+                               'width':w\r
+                       });\r
+               }\r
+               var h=window.ie?wrapper.offsetHeight:h2.offsetHeight+form.offsetHeight+row.offsetHeight,q=window.ie?1:0,r=window.ie?0:4;\r
+               if(parseFloat(h)>parseFloat(a.y*.9)){\r
+                       h=parseInt(a.y*.9);\r
+                       var h3=h-row.offsetHeight-h2.offsetHeight-q;\r
+                       form.setStyles({\r
+                               'margin':'0 auto',\r
+                               'overflow':'auto',\r
+                               'height':h3,\r
+                               'max-height':h3\r
+                       });\r
+               }else{\r
+                       var h3=h-row.offsetHeight-h2.offsetHeight-q;\r
+                       form.setStyles({\r
+                               'overflow':'auto',\r
+                               'width':'100%',\r
+                               'max-height':h3\r
+                       });\r
+               }\r
+               wrapper.setStyles({\r
+                       'position':pos,\r
+                       'left':scrollAt.x+a.x/2-w/2,\r
+                       'top':scrollAt.y+a.y/2-h/2,\r
+                       'z-index':3\r
+               });\r
+       }\r
+       wrapper.addEvent('keyup',function(e){\r
+               e=new Event(e);\r
+               e.stop();\r
+       });\r
+       kfm_resizeHandler_add('shader');\r
+       kdnd_makeDraggable('modal_dialog');\r
+}\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/mootools.v1.11/.htaccess b/ipf/admin/media/tiny_mce/plugins/kfm/j/mootools.v1.11/.htaccess
new file mode 100644 (file)
index 0000000..4439849
--- /dev/null
@@ -0,0 +1,4 @@
+<IfModule mod_expires.c>
+       ExpiresActive On
+       ExpiresDefault "access plus 52 weeks"
+</IfModule>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/mootools.v1.11/mootools.v1.11.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/mootools.v1.11/mootools.v1.11.js
new file mode 100644 (file)
index 0000000..289183a
--- /dev/null
@@ -0,0 +1,4352 @@
+/*
+Script: Core.js
+       Mootools - My Object Oriented javascript.
+
+License:
+       MIT-style license.
+
+MooTools Copyright:
+       copyright (c) 2007 Valerio Proietti, <http://mad4milk.net>
+
+MooTools Credits:
+       - Class is slightly based on Base.js <http://dean.edwards.name/weblog/2006/03/base/> (c) 2006 Dean Edwards, License <http://creativecommons.org/licenses/LGPL/2.1/>
+       - Some functions are inspired by those found in prototype.js <http://prototype.conio.net/> (c) 2005 Sam Stephenson sam [at] conio [dot] net, MIT-style license
+       - Documentation by Aaron Newton (aaron.newton [at] cnet [dot] com) and Valerio Proietti.
+*/
+
+var MooTools = {
+       version: '1.11'
+};
+
+/* Section: Core Functions */
+
+/*
+Function: $defined
+       Returns true if the passed in value/object is defined, that means is not null or undefined.
+
+Arguments:
+       obj - object to inspect
+*/
+
+function $defined(obj){
+       return (obj != undefined);
+};
+
+/*
+Function: $type
+       Returns the type of object that matches the element passed in.
+
+Arguments:
+       obj - the object to inspect.
+
+Example:
+       >var myString = 'hello';
+       >$type(myString); //returns "string"
+
+Returns:
+       'element' - if obj is a DOM element node
+       'textnode' - if obj is a DOM text node
+       'whitespace' - if obj is a DOM whitespace node
+       'arguments' - if obj is an arguments object
+       'object' - if obj is an object
+       'string' - if obj is a string
+       'number' - if obj is a number
+       'boolean' - if obj is a boolean
+       'function' - if obj is a function
+       'regexp' - if obj is a regular expression
+       'class' - if obj is a Class. (created with new Class, or the extend of another class).
+       'collection' - if obj is a native htmlelements collection, such as childNodes, getElementsByTagName .. etc.
+       false - (boolean) if the object is not defined or none of the above.
+*/
+
+function $type(obj){
+       if (!$defined(obj)) return false;
+       if (obj.htmlElement) return 'element';
+       var type = typeof obj;
+       if (type == 'object' && obj.nodeName){
+               switch(obj.nodeType){
+                       case 1: return 'element';
+                       case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
+               }
+       }
+       if (type == 'object' || type == 'function'){
+               switch(obj.constructor){
+                       case Array: return 'array';
+                       case RegExp: return 'regexp';
+                       case Class: return 'class';
+               }
+               if (typeof obj.length == 'number'){
+                       if (obj.item) return 'collection';
+                       if (obj.callee) return 'arguments';
+               }
+       }
+       return type;
+};
+
+/*
+Function: $merge
+       merges a number of objects recursively without referencing them or their sub-objects.
+
+Arguments:
+       any number of objects.
+
+Example:
+       >var mergedObj = $merge(obj1, obj2, obj3);
+       >//obj1, obj2, and obj3 are unaltered
+*/
+
+function $merge(){
+       var mix = {};
+       for (var i = 0; i < arguments.length; i++){
+               for (var property in arguments[i]){
+                       var ap = arguments[i][property];
+                       var mp = mix[property];
+                       if (mp && $type(ap) == 'object' && $type(mp) == 'object') mix[property] = $merge(mp, ap);
+                       else mix[property] = ap;
+               }
+       }
+       return mix;
+};
+
+/*
+Function: $extend
+       Copies all the properties from the second passed object to the first passed Object.
+       If you do myWhatever.extend = $extend the first parameter will become myWhatever, and your extend function will only need one parameter.
+
+Example:
+       (start code)
+       var firstOb = {
+               'name': 'John',
+               'lastName': 'Doe'
+       };
+       var secondOb = {
+               'age': '20',
+               'sex': 'male',
+               'lastName': 'Dorian'
+       };
+       $extend(firstOb, secondOb);
+       //firstOb will become:
+       {
+               'name': 'John',
+               'lastName': 'Dorian',
+               'age': '20',
+               'sex': 'male'
+       };
+       (end)
+
+Returns:
+       The first object, extended.
+*/
+
+var $extend = function(){
+       var args = arguments;
+       if (!args[1]) args = [this, args[0]];
+       for (var property in args[1]) args[0][property] = args[1][property];
+       return args[0];
+};
+
+/*
+Function: $native
+       Will add a .extend method to the objects passed as a parameter, but the property passed in will be copied to the object's prototype only if non previously existent.
+       Its handy if you dont want the .extend method of an object to overwrite existing methods.
+       Used automatically in MooTools to implement Array/String/Function/Number methods to browser that dont support them whitout manual checking.
+
+Arguments:
+       a number of classes/native javascript objects
+
+*/
+
+var $native = function(){
+       for (var i = 0, l = arguments.length; i < l; i++){
+               arguments[i].extend = function(props){
+                       for (var prop in props){
+                               if (!this.prototype[prop]) this.prototype[prop] = props[prop];
+                               if (!this[prop]) this[prop] = $native.generic(prop);
+                       }
+               };
+       }
+};
+
+$native.generic = function(prop){
+       return function(bind){
+               return this.prototype[prop].apply(bind, Array.prototype.slice.call(arguments, 1));
+       };
+};
+
+$native(Function, Array, String, Number);
+
+/*
+Function: $chk
+       Returns true if the passed in value/object exists or is 0, otherwise returns false.
+       Useful to accept zeroes.
+
+Arguments:
+       obj - object to inspect
+*/
+
+function $chk(obj){
+       return !!(obj || obj === 0);
+};
+
+/*
+Function: $pick
+       Returns the first object if defined, otherwise returns the second.
+
+Arguments:
+       obj - object to test
+       picked - the default to return
+
+Example:
+       (start code)
+               function say(msg){
+                       alert($pick(msg, 'no meessage supplied'));
+               }
+       (end)
+*/
+
+function $pick(obj, picked){
+       return $defined(obj) ? obj : picked;
+};
+
+/*
+Function: $random
+       Returns a random integer number between the two passed in values.
+
+Arguments:
+       min - integer, the minimum value (inclusive).
+       max - integer, the maximum value (inclusive).
+
+Returns:
+       a random integer between min and max.
+*/
+
+function $random(min, max){
+       return Math.floor(Math.random() * (max - min + 1) + min);
+};
+
+/*
+Function: $time
+       Returns the current timestamp
+
+Returns:
+       a timestamp integer.
+*/
+
+function $time(){
+       return new Date().getTime();
+};
+
+/*
+Function: $clear
+       clears a timeout or an Interval.
+
+Returns:
+       null
+
+Arguments:
+       timer - the setInterval or setTimeout to clear.
+
+Example:
+       >var myTimer = myFunction.delay(5000); //wait 5 seconds and execute my function.
+       >myTimer = $clear(myTimer); //nevermind
+
+See also:
+       <Function.delay>, <Function.periodical>
+*/
+
+function $clear(timer){
+       clearTimeout(timer);
+       clearInterval(timer);
+       return null;
+};
+
+/*
+Class: Abstract
+       Abstract class, to be used as singleton. Will add .extend to any object
+
+Arguments:
+       an object
+
+Returns:
+       the object with an .extend property, equivalent to <$extend>.
+*/
+
+var Abstract = function(obj){
+       obj = obj || {};
+       obj.extend = $extend;
+       return obj;
+};
+
+//window, document
+
+var Window = new Abstract(window);
+var Document = new Abstract(document);
+document.head = document.getElementsByTagName('head')[0];
+
+/*
+Class: window
+       Some properties are attached to the window object by the browser detection.
+       
+Note:
+       browser detection is entirely object-based. We dont sniff.
+
+Properties:
+       window.ie - will be set to true if the current browser is internet explorer (any).
+       window.ie6 - will be set to true if the current browser is internet explorer 6.
+       window.ie7 - will be set to true if the current browser is internet explorer 7.
+       window.gecko - will be set to true if the current browser is Mozilla/Gecko.
+       window.webkit - will be set to true if the current browser is Safari/Konqueror.
+       window.webkit419 - will be set to true if the current browser is Safari2 / webkit till version 419.
+       window.webkit420 - will be set to true if the current browser is Safari3 (Webkit SVN Build) / webkit over version 419.
+       window.opera - is set to true by opera itself.
+*/
+
+window.xpath = !!(document.evaluate);
+if (window.ActiveXObject) window.ie = window[window.XMLHttpRequest ? 'ie7' : 'ie6'] = true;
+else if (document.childNodes && !document.all && !navigator.taintEnabled) window.webkit = window[window.xpath ? 'webkit420' : 'webkit419'] = true;
+else if (document.getBoxObjectFor != null) window.gecko = true;
+
+/*compatibility*/
+
+window.khtml = window.webkit;
+
+Object.extend = $extend;
+
+/*end compatibility*/
+
+//htmlelement
+
+if (typeof HTMLElement == 'undefined'){
+       var HTMLElement = function(){};
+       if (window.webkit) document.createElement("iframe"); //fixes safari
+       HTMLElement.prototype = (window.webkit) ? window["[[DOMElement.prototype]]"] : {};
+}
+HTMLElement.prototype.htmlElement = function(){};
+
+//enables background image cache for internet explorer 6
+
+if (window.ie6) try {document.execCommand("BackgroundImageCache", false, true);} catch(e){};
+
+/*
+Script: Class.js
+       Contains the Class Function, aims to ease the creation of reusable Classes.
+
+License:
+       MIT-style license.
+*/
+
+/*
+Class: Class
+       The base class object of the <http://mootools.net> framework.
+       Creates a new class, its initialize method will fire upon class instantiation.
+       Initialize wont fire on instantiation when you pass *null*.
+
+Arguments:
+       properties - the collection of properties that apply to the class.
+
+Example:
+       (start code)
+       var Cat = new Class({
+               initialize: function(name){
+                       this.name = name;
+               }
+       });
+       var myCat = new Cat('Micia');
+       alert(myCat.name); //alerts 'Micia'
+       (end)
+*/
+
+var Class = function(properties){
+       var klass = function(){
+               return (arguments[0] !== null && this.initialize && $type(this.initialize) == 'function') ? this.initialize.apply(this, arguments) : this;
+       };
+       $extend(klass, this);
+       klass.prototype = properties;
+       klass.constructor = Class;
+       return klass;
+};
+
+/*
+Property: empty
+       Returns an empty function
+*/
+
+Class.empty = function(){};
+
+Class.prototype = {
+
+       /*
+       Property: extend
+               Returns the copy of the Class extended with the passed in properties.
+
+       Arguments:
+               properties - the properties to add to the base class in this new Class.
+
+       Example:
+               (start code)
+               var Animal = new Class({
+                       initialize: function(age){
+                               this.age = age;
+                       }
+               });
+               var Cat = Animal.extend({
+                       initialize: function(name, age){
+                               this.parent(age); //will call the previous initialize;
+                               this.name = name;
+                       }
+               });
+               var myCat = new Cat('Micia', 20);
+               alert(myCat.name); //alerts 'Micia'
+               alert(myCat.age); //alerts 20
+               (end)
+       */
+
+       extend: function(properties){
+               var proto = new this(null);
+               for (var property in properties){
+                       var pp = proto[property];
+                       proto[property] = Class.Merge(pp, properties[property]);
+               }
+               return new Class(proto);
+       },
+
+       /*
+       Property: implement
+               Implements the passed in properties to the base Class prototypes, altering the base class, unlike <Class.extend>.
+
+       Arguments:
+               properties - the properties to add to the base class.
+
+       Example:
+               (start code)
+               var Animal = new Class({
+                       initialize: function(age){
+                               this.age = age;
+                       }
+               });
+               Animal.implement({
+                       setName: function(name){
+                               this.name = name
+                       }
+               });
+               var myAnimal = new Animal(20);
+               myAnimal.setName('Micia');
+               alert(myAnimal.name); //alerts 'Micia'
+               (end)
+       */
+
+       implement: function(){
+               for (var i = 0, l = arguments.length; i < l; i++) $extend(this.prototype, arguments[i]);
+       }
+
+};
+
+//internal
+
+Class.Merge = function(previous, current){
+       if (previous && previous != current){
+               var type = $type(current);
+               if (type != $type(previous)) return current;
+               switch(type){
+                       case 'function':
+                               var merged = function(){
+                                       this.parent = arguments.callee.parent;
+                                       return current.apply(this, arguments);
+                               };
+                               merged.parent = previous;
+                               return merged;
+                       case 'object': return $merge(previous, current);
+               }
+       }
+       return current;
+};
+
+/*
+Script: Class.Extras.js
+       Contains common implementations for custom classes. In Mootools is implemented in <Ajax>, <XHR> and <Fx.Base> and many more.
+
+License:
+       MIT-style license.
+*/
+
+/*
+Class: Chain
+       An "Utility" Class. Its methods can be implemented with <Class.implement> into any <Class>.
+       Currently implemented in <Fx.Base>, <XHR> and <Ajax>. In <Fx.Base> for example, is used to execute a list of function, one after another, once the effect is completed.
+       The functions will not be fired all togheter, but one every completion, to create custom complex animations.
+
+Example:
+       (start code)
+       var myFx = new Fx.Style('element', 'opacity');
+
+       myFx.start(1,0).chain(function(){
+               myFx.start(0,1);
+       }).chain(function(){
+               myFx.start(1,0);
+       }).chain(function(){
+               myFx.start(0,1);
+       });
+       //the element will appear and disappear three times
+       (end)
+*/
+
+var Chain = new Class({
+
+       /*
+       Property: chain
+               adds a function to the Chain instance stack.
+
+       Arguments:
+               fn - the function to append.
+       */
+
+       chain: function(fn){
+               this.chains = this.chains || [];
+               this.chains.push(fn);
+               return this;
+       },
+
+       /*
+       Property: callChain
+               Executes the first function of the Chain instance stack, then removes it. The first function will then become the second.
+       */
+
+       callChain: function(){
+               if (this.chains && this.chains.length) this.chains.shift().delay(10, this);
+       },
+
+       /*
+       Property: clearChain
+               Clears the stack of a Chain instance.
+       */
+
+       clearChain: function(){
+               this.chains = [];
+       }
+
+});
+
+/*
+Class: Events
+       An "Utility" Class. Its methods can be implemented with <Class.implement> into any <Class>.
+       In <Fx.Base> Class, for example, is used to give the possibility add any number of functions to the Effects events, like onComplete, onStart, onCancel.
+       Events in a Class that implements <Events> can be either added as an option, or with addEvent. Never with .options.onEventName.
+
+Example:
+       (start code)
+       var myFx = new Fx.Style('element', 'opacity').addEvent('onComplete', function(){
+               alert('the effect is completed');
+       }).addEvent('onComplete', function(){
+               alert('I told you the effect is completed');
+       });
+
+       myFx.start(0,1);
+       //upon completion it will display the 2 alerts, in order.
+       (end)
+
+Implementing:
+       This class can be implemented into other classes to add the functionality to them.
+       Goes well with the <Options> class.
+
+Example:
+       (start code)
+       var Widget = new Class({
+               initialize: function(){},
+               finish: function(){
+                       this.fireEvent('onComplete');
+               }
+       });
+       Widget.implement(new Events);
+       //later...
+       var myWidget = new Widget();
+       myWidget.addEvent('onComplete', myfunction);
+       (end)
+*/
+
+var Events = new Class({
+
+       /*
+       Property: addEvent
+               adds an event to the stack of events of the Class instance.
+
+       Arguments:
+               type - string; the event name (e.g. 'onComplete')
+               fn - function to execute
+       */
+
+       addEvent: function(type, fn){
+               if (fn != Class.empty){
+                       this.$events = this.$events || {};
+                       this.$events[type] = this.$events[type] || [];
+                       this.$events[type].include(fn);
+               }
+               return this;
+       },
+
+       /*
+       Property: fireEvent
+               fires all events of the specified type in the Class instance.
+
+       Arguments:
+               type - string; the event name (e.g. 'onComplete')
+               args - array or single object; arguments to pass to the function; if more than one argument, must be an array
+               delay - (integer) delay (in ms) to wait to execute the event
+
+       Example:
+       (start code)
+       var Widget = new Class({
+               initialize: function(arg1, arg2){
+                       ...
+                       this.fireEvent("onInitialize", [arg1, arg2], 50);
+               }
+       });
+       Widget.implement(new Events);
+       (end)
+       */
+
+       fireEvent: function(type, args, delay){
+               if (this.$events && this.$events[type]){
+                       this.$events[type].each(function(fn){
+                               fn.create({'bind': this, 'delay': delay, 'arguments': args})();
+                       }, this);
+               }
+               return this;
+       },
+
+       /*
+       Property: removeEvent
+               removes an event from the stack of events of the Class instance.
+
+       Arguments:
+               type - string; the event name (e.g. 'onComplete')
+               fn - function that was added
+       */
+
+       removeEvent: function(type, fn){
+               if (this.$events && this.$events[type]) this.$events[type].remove(fn);
+               return this;
+       }
+
+});
+
+/*
+Class: Options
+       An "Utility" Class. Its methods can be implemented with <Class.implement> into any <Class>.
+       Used to automate the options settings, also adding Class <Events> when the option begins with on.
+
+       Example:
+               (start code)
+               var Widget = new Class({
+                       options: {
+                               color: '#fff',
+                               size: {
+                                       width: 100
+                                       height: 100
+                               }
+                       },
+                       initialize: function(options){
+                               this.setOptions(options);
+                       }
+               });
+               Widget.implement(new Options);
+               //later...
+               var myWidget = new Widget({
+                       color: '#f00',
+                       size: {
+                               width: 200
+                       }
+               });
+               //myWidget.options = {color: #f00, size: {width: 200, height: 100}}
+               (end)
+*/
+
+var Options = new Class({
+
+       /*
+       Property: setOptions
+               sets this.options
+
+       Arguments:
+               defaults - object; the default set of options
+               options - object; the user entered options. can be empty too.
+
+       Note:
+               if your Class has <Events> implemented, every option beginning with on, followed by a capital letter (onComplete) becomes an Class instance event.
+       */
+
+       setOptions: function(){
+               this.options = $merge.apply(null, [this.options].extend(arguments));
+               if (this.addEvent){
+                       for (var option in this.options){
+                               if ($type(this.options[option] == 'function') && (/^on[A-Z]/).test(option)) this.addEvent(option, this.options[option]);
+                       }
+               }
+               return this;
+       }
+
+});
+
+/*
+Script: Array.js
+       Contains Array prototypes, <$A>, <$each>
+
+License:
+       MIT-style license.
+*/
+
+/*
+Class: Array
+       A collection of The Array Object prototype methods.
+*/
+
+//custom methods
+
+Array.extend({
+
+       /*
+       Property: forEach
+               Iterates through an array; This method is only available for browsers without native *forEach* support.
+               For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach>
+
+               *forEach* executes the provided function (callback) once for each element present in the array. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
+
+       Arguments:
+               fn - function to execute with each item in the array; passed the item and the index of that item in the array
+               bind - the object to bind "this" to (see <Function.bind>)
+
+       Example:
+               >['apple','banana','lemon'].each(function(item, index){
+               >       alert(index + " = " + item); //alerts "0 = apple" etc.
+               >}, bindObj); //optional second arg for binding, not used here
+       */
+
+       forEach: function(fn, bind){
+               for (var i = 0, j = this.length; i < j; i++) fn.call(bind, this[i], i, this);
+       },
+
+       /*
+       Property: filter
+               This method is provided only for browsers without native *filter* support.
+               For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:filter>
+
+               *filter* calls a provided callback function once for each element in an array, and constructs a new array of all the values for which callback returns a true value. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values. Array elements which do not pass the callback test are simply skipped, and are not included in the new array.
+
+       Arguments:
+               fn - function to execute with each item in the array; passed the item and the index of that item in the array
+               bind - the object to bind "this" to (see <Function.bind>)
+
+       Example:
+               >var biggerThanTwenty = [10,3,25,100].filter(function(item, index){
+               > return item > 20;
+               >});
+               >//biggerThanTwenty = [25,100]
+       */
+
+       filter: function(fn, bind){
+               var results = [];
+               for (var i = 0, j = this.length; i < j; i++){
+                       if (fn.call(bind, this[i], i, this)) results.push(this[i]);
+               }
+               return results;
+       },
+
+       /*
+       Property: map
+               This method is provided only for browsers without native *map* support.
+               For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:map>
+
+               *map* calls a provided callback function once for each element in an array, in order, and constructs a new array from the results. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
+
+       Arguments:
+               fn - function to execute with each item in the array; passed the item and the index of that item in the array
+               bind - the object to bind "this" to (see <Function.bind>)
+
+       Example:
+               >var timesTwo = [1,2,3].map(function(item, index){
+               > return item*2;
+               >});
+               >//timesTwo = [2,4,6];
+       */
+
+       map: function(fn, bind){
+               var results = [];
+               for (var i = 0, j = this.length; i < j; i++) results[i] = fn.call(bind, this[i], i, this);
+               return results;
+       },
+
+       /*
+       Property: every
+               This method is provided only for browsers without native *every* support.
+               For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every>
+
+               *every* executes the provided callback function once for each element present in the array until it finds one where callback returns a false value. If such an element is found, the every method immediately returns false. Otherwise, if callback returned a true value for all elements, every will return true. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
+
+       Arguments:
+               fn - function to execute with each item in the array; passed the item and the index of that item in the array
+               bind - the object to bind "this" to (see <Function.bind>)
+
+       Example:
+               >var areAllBigEnough = [10,4,25,100].every(function(item, index){
+               > return item > 20;
+               >});
+               >//areAllBigEnough = false
+       */
+
+       every: function(fn, bind){
+               for (var i = 0, j = this.length; i < j; i++){
+                       if (!fn.call(bind, this[i], i, this)) return false;
+               }
+               return true;
+       },
+
+       /*
+       Property: some
+               This method is provided only for browsers without native *some* support.
+               For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some>
+
+               *some* executes the callback function once for each element present in the array until it finds one where callback returns a true value. If such an element is found, some immediately returns true. Otherwise, some returns false. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
+
+       Arguments:
+               fn - function to execute with each item in the array; passed the item and the index of that item in the array
+               bind - the object to bind "this" to (see <Function.bind>)
+
+       Example:
+               >var isAnyBigEnough = [10,4,25,100].some(function(item, index){
+               > return item > 20;
+               >});
+               >//isAnyBigEnough = true
+       */
+
+       some: function(fn, bind){
+               for (var i = 0, j = this.length; i < j; i++){
+                       if (fn.call(bind, this[i], i, this)) return true;
+               }
+               return false;
+       },
+
+       /*
+       Property: indexOf
+               This method is provided only for browsers without native *indexOf* support.
+               For more info see <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf>
+
+               *indexOf* compares a search element to elements of the Array using strict equality (the same method used by the ===, or triple-equals, operator).
+
+       Arguments:
+               item - any type of object; element to locate in the array
+               from - integer; optional; the index of the array at which to begin the search (defaults to 0)
+
+       Example:
+               >['apple','lemon','banana'].indexOf('lemon'); //returns 1
+               >['apple','lemon'].indexOf('banana'); //returns -1
+       */
+
+       indexOf: function(item, from){
+               var len = this.length;
+               for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
+                       if (this[i] === item) return i;
+               }
+               return -1;
+       },
+
+       /*
+       Property: each
+               Same as <Array.forEach>.
+
+       Arguments:
+               fn - function to execute with each item in the array; passed the item and the index of that item in the array
+               bind - optional, the object that the "this" of the function will refer to.
+
+       Example:
+               >var Animals = ['Cat', 'Dog', 'Coala'];
+               >Animals.each(function(animal){
+               >       document.write(animal)
+               >});
+       */
+
+       /*
+       Property: copy
+               returns a copy of the array.
+
+       Returns:
+               a new array which is a copy of the current one.
+
+       Arguments:
+               start - integer; optional; the index where to start the copy, default is 0. If negative, it is taken as the offset from the end of the array.
+               length - integer; optional; the number of elements to copy. By default, copies all elements from start to the end of the array.
+
+       Example:
+               >var letters = ["a","b","c"];
+               >var copy = letters.copy();             // ["a","b","c"] (new instance)
+       */
+
+       copy: function(start, length){
+               start = start || 0;
+               if (start < 0) start = this.length + start;
+               length = length || (this.length - start);
+               var newArray = [];
+               for (var i = 0; i < length; i++) newArray[i] = this[start++];
+               return newArray;
+       },
+
+       /*
+       Property: remove
+               Removes all occurrences of an item from the array.
+
+       Arguments:
+               item - the item to remove
+
+       Returns:
+               the Array with all occurrences of the item removed.
+
+       Example:
+               >["1","2","3","2"].remove("2") // ["1","3"];
+       */
+
+       remove: function(item){
+               var i = 0;
+               var len = this.length;
+               while (i < len){
+                       if (this[i] === item){
+                               this.splice(i, 1);
+                               len--;
+                       } else {
+                               i++;
+                       }
+               }
+               return this;
+       },
+
+       /*
+       Property: contains
+               Tests an array for the presence of an item.
+
+       Arguments:
+               item - the item to search for in the array.
+               from - integer; optional; the index at which to begin the search, default is 0. If negative, it is taken as the offset from the end of the array.
+
+       Returns:
+               true - the item was found
+               false - it wasn't
+
+       Example:
+               >["a","b","c"].contains("a"); // true
+               >["a","b","c"].contains("d"); // false
+       */
+
+       contains: function(item, from){
+               return this.indexOf(item, from) != -1;
+       },
+
+       /*
+       Property: associate
+               Creates an object with key-value pairs based on the array of keywords passed in
+               and the current content of the array.
+
+       Arguments:
+               keys - the array of keywords.
+
+       Example:
+               (start code)
+               var Animals = ['Cat', 'Dog', 'Coala', 'Lizard'];
+               var Speech = ['Miao', 'Bau', 'Fruuu', 'Mute'];
+               var Speeches = Animals.associate(Speech);
+               //Speeches['Miao'] is now Cat.
+               //Speeches['Bau'] is now Dog.
+               //...
+               (end)
+       */
+
+       associate: function(keys){
+               var obj = {}, length = Math.min(this.length, keys.length);
+               for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
+               return obj;
+       },
+
+       /*
+       Property: extend
+               Extends an array with another one.
+
+       Arguments:
+               array - the array to extend ours with
+
+       Example:
+               >var Animals = ['Cat', 'Dog', 'Coala'];
+               >Animals.extend(['Lizard']);
+               >//Animals is now: ['Cat', 'Dog', 'Coala', 'Lizard'];
+       */
+
+       extend: function(array){
+               for (var i = 0, j = array.length; i < j; i++) this.push(array[i]);
+               return this;
+       },
+
+       /*
+       Property: merge
+               merges an array in another array, without duplicates. (case- and type-sensitive)
+
+       Arguments:
+               array - the array to merge from.
+
+       Example:
+               >['Cat','Dog'].merge(['Dog','Coala']); //returns ['Cat','Dog','Coala']
+       */
+
+       merge: function(array){
+               for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
+               return this;
+       },
+
+       /*
+       Property: include
+               includes the passed in element in the array, only if its not already present. (case- and type-sensitive)
+
+       Arguments:
+               item - item to add to the array (if not present)
+
+       Example:
+               >['Cat','Dog'].include('Dog'); //returns ['Cat','Dog']
+               >['Cat','Dog'].include('Coala'); //returns ['Cat','Dog','Coala']
+       */
+
+       include: function(item){
+               if (!this.contains(item)) this.push(item);
+               return this;
+       },
+
+       /*
+       Property: getRandom
+               returns a random item in the Array
+       */
+
+       getRandom: function(){
+               return this[$random(0, this.length - 1)] || null;
+       },
+
+       /*
+       Property: getLast
+               returns the last item in the Array
+       */
+
+       getLast: function(){
+               return this[this.length - 1] || null;
+       }
+
+});
+
+//copies
+
+Array.prototype.each = Array.prototype.forEach;
+Array.each = Array.forEach;
+
+/* Section: Utility Functions */
+
+/*
+Function: $A()
+       Same as <Array.copy>, but as function.
+       Useful to apply Array prototypes to iterable objects, as a collection of DOM elements or the arguments object.
+
+Example:
+       (start code)
+       function myFunction(){
+               $A(arguments).each(argument, function(){
+                       alert(argument);
+               });
+       };
+       //the above will alert all the arguments passed to the function myFunction.
+       (end)
+*/
+
+function $A(array){
+       return Array.copy(array);
+};
+
+/*
+Function: $each
+       Use to iterate through iterables that are not regular arrays, such as builtin getElementsByTagName calls, arguments of a function, or an object.
+
+Arguments:
+       iterable - an iterable element or an objct.
+       function - function to apply to the iterable.
+       bind - optional, the 'this' of the function will refer to this object.
+
+Function argument:
+       The function argument will be passed the following arguments.
+
+       item - the current item in the iterator being procesed
+       index - integer; the index of the item, or key in case of an object.
+
+Examples:
+       (start code)
+       $each(['Sun','Mon','Tue'], function(day, index){
+               alert('name:' + day + ', index: ' + index);
+       });
+       //alerts "name: Sun, index: 0", "name: Mon, index: 1", etc.
+       //over an object
+       $each({first: "Sunday", second: "Monday", third: "Tuesday"}, function(value, key){
+               alert("the " + key + " day of the week is " + value);
+       });
+       //alerts "the first day of the week is Sunday",
+       //"the second day of the week is Monday", etc.
+       (end)
+*/
+
+function $each(iterable, fn, bind){
+       if (iterable && typeof iterable.length == 'number' && $type(iterable) != 'object'){
+               Array.forEach(iterable, fn, bind);
+       } else {
+                for (var name in iterable) fn.call(bind || iterable, iterable[name], name);
+       }
+};
+
+/*compatibility*/
+
+Array.prototype.test = Array.prototype.contains;
+
+/*end compatibility*/
+
+/*
+Script: String.js
+       Contains String prototypes.
+
+License:
+       MIT-style license.
+*/
+
+/*
+Class: String
+       A collection of The String Object prototype methods.
+*/
+
+String.extend({
+
+       /*
+       Property: test
+               Tests a string with a regular expression.
+
+       Arguments:
+               regex - a string or regular expression object, the regular expression you want to match the string with
+               params - optional, if first parameter is a string, any parameters you want to pass to the regex ('g' has no effect)
+
+       Returns:
+               true if a match for the regular expression is found in the string, false if not.
+               See <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:RegExp:test>
+
+       Example:
+               >"I like cookies".test("cookie"); // returns true
+               >"I like cookies".test("COOKIE", "i") // ignore case, returns true
+               >"I like cookies".test("cake"); // returns false
+       */
+
+       test: function(regex, params){
+               return (($type(regex) == 'string') ? new RegExp(regex, params) : regex).test(this);
+       },
+
+       /*
+       Property: toInt
+               parses a string to an integer.
+
+       Returns:
+               either an int or "NaN" if the string is not a number.
+
+       Example:
+               >var value = "10px".toInt(); // value is 10
+       */
+
+       toInt: function(){
+               return parseInt(this, 10);
+       },
+
+       /*
+       Property: toFloat
+               parses a string to an float.
+
+       Returns:
+               either a float or "NaN" if the string is not a number.
+
+       Example:
+               >var value = "10.848".toFloat(); // value is 10.848
+       */
+
+       toFloat: function(){
+               return parseFloat(this);
+       },
+
+       /*
+       Property: camelCase
+               Converts a hiphenated string to a camelcase string.
+
+       Example:
+               >"I-like-cookies".camelCase(); //"ILikeCookies"
+
+       Returns:
+               the camel cased string
+       */
+
+       camelCase: function(){
+               return this.replace(/-\D/g, function(match){
+                       return match.charAt(1).toUpperCase();
+               });
+       },
+
+       /*
+       Property: hyphenate
+               Converts a camelCased string to a hyphen-ated string.
+
+       Example:
+               >"ILikeCookies".hyphenate(); //"I-like-cookies"
+       */
+
+       hyphenate: function(){
+               return this.replace(/\w[A-Z]/g, function(match){
+                       return (match.charAt(0) + '-' + match.charAt(1).toLowerCase());
+               });
+       },
+
+       /*
+       Property: capitalize
+               Converts the first letter in each word of a string to Uppercase.
+
+       Example:
+               >"i like cookies".capitalize(); //"I Like Cookies"
+
+       Returns:
+               the capitalized string
+       */
+
+       capitalize: function(){
+               return this.replace(/\b[a-z]/g, function(match){
+                       return match.toUpperCase();
+               });
+       },
+
+       /*
+       Property: trim
+               Trims the leading and trailing spaces off a string.
+
+       Example:
+               >"    i like cookies     ".trim() //"i like cookies"
+
+       Returns:
+               the trimmed string
+       */
+
+       trim: function(){
+               return this.replace(/^\s+|\s+$/g, '');
+       },
+
+       /*
+       Property: clean
+               trims (<String.trim>) a string AND removes all the double spaces in a string.
+
+       Returns:
+               the cleaned string
+
+       Example:
+               >" i      like     cookies      \n\n".clean() //"i like cookies"
+       */
+
+       clean: function(){
+               return this.replace(/\s{2,}/g, ' ').trim();
+       },
+
+       /*
+       Property: rgbToHex
+               Converts an RGB value to hexidecimal. The string must be in the format of "rgb(255,255,255)" or "rgba(255,255,255,1)";
+
+       Arguments:
+               array - boolean value, defaults to false. Use true if you want the array ['FF','33','00'] as output instead of "#FF3300"
+
+       Returns:
+               hex string or array. returns "transparent" if the output is set as string and the fourth value of rgba in input string is 0.
+
+       Example:
+               >"rgb(17,34,51)".rgbToHex(); //"#112233"
+               >"rgba(17,34,51,0)".rgbToHex(); //"transparent"
+               >"rgb(17,34,51)".rgbToHex(true); //['11','22','33']
+       */
+
+       rgbToHex: function(array){
+               var rgb = this.match(/\d{1,3}/g);
+               return (rgb) ? rgb.rgbToHex(array) : false;
+       },
+
+       /*
+       Property: hexToRgb
+               Converts a hexidecimal color value to RGB. Input string must be the hex color value (with or without the hash). Also accepts triplets ('333');
+
+       Arguments:
+               array - boolean value, defaults to false. Use true if you want the array [255,255,255] as output instead of "rgb(255,255,255)";
+
+       Returns:
+               rgb string or array.
+
+       Example:
+               >"#112233".hexToRgb(); //"rgb(17,34,51)"
+               >"#112233".hexToRgb(true); //[17,34,51]
+       */
+
+       hexToRgb: function(array){
+               var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
+               return (hex) ? hex.slice(1).hexToRgb(array) : false;
+       },
+
+       /*
+       Property: contains
+               checks if the passed in string is contained in the String. also accepts an optional second parameter, to check if the string is contained in a list of separated values.
+
+       Example:
+               >'a b c'.contains('c', ' '); //true
+               >'a bc'.contains('bc'); //true
+               >'a bc'.contains('b', ' '); //false
+       */
+
+       contains: function(string, s){
+               return (s) ? (s + this + s).indexOf(s + string + s) > -1 : this.indexOf(string) > -1;
+       },
+
+       /*
+       Property: escapeRegExp
+               Returns string with escaped regular expression characters
+
+       Example:
+               >var search = 'animals.sheeps[1]'.escapeRegExp(); // search is now 'animals\.sheeps\[1\]'
+
+       Returns:
+               Escaped string
+       */
+
+       escapeRegExp: function(){
+               return this.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
+       }
+
+});
+
+Array.extend({
+
+       /*
+       Property: rgbToHex
+               see <String.rgbToHex>, but as an array method.
+       */
+
+       rgbToHex: function(array){
+               if (this.length < 3) return false;
+               if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
+               var hex = [];
+               for (var i = 0; i < 3; i++){
+                       var bit = (this[i] - 0).toString(16);
+                       hex.push((bit.length == 1) ? '0' + bit : bit);
+               }
+               return array ? hex : '#' + hex.join('');
+       },
+
+       /*
+       Property: hexToRgb
+               same as <String.hexToRgb>, but as an array method.
+       */
+
+       hexToRgb: function(array){
+               if (this.length != 3) return false;
+               var rgb = [];
+               for (var i = 0; i < 3; i++){
+                       rgb.push(parseInt((this[i].length == 1) ? this[i] + this[i] : this[i], 16));
+               }
+               return array ? rgb : 'rgb(' + rgb.join(',') + ')';
+       }
+
+});
+
+/* 
+Script: Function.js
+       Contains Function prototypes and utility functions .
+
+License:
+       MIT-style license.
+
+Credits:
+       - Some functions are inspired by those found in prototype.js <http://prototype.conio.net/> (c) 2005 Sam Stephenson sam [at] conio [dot] net, MIT-style license
+*/
+
+/*
+Class: Function
+       A collection of The Function Object prototype methods.
+*/
+
+Function.extend({
+
+       /*
+       Property: create
+               Main function to create closures.
+
+       Returns:
+               a function.
+
+       Arguments:
+               options - An Options object.
+
+       Options:
+               bind - The object that the "this" of the function will refer to. Default is the current function.
+               event - If set to true, the function will act as an event listener and receive an event as first argument.
+                               If set to a class name, the function will receive a new instance of this class (with the event passed as argument's constructor) as first argument.
+                               Default is false.
+               arguments - A single argument or array of arguments that will be passed to the function when called.
+               
+                                       If both the event and arguments options are set, the event is passed as first argument and the arguments array will follow.
+                                       
+                                       Default is no custom arguments, the function will receive the standard arguments when called.
+                                       
+               delay - Numeric value: if set, the returned function will delay the actual execution by this amount of milliseconds and return a timer handle when called.
+                               Default is no delay.
+               periodical - Numeric value: if set, the returned function will periodically perform the actual execution with this specified interval and return a timer handle when called.
+                               Default is no periodical execution.
+               attempt - If set to true, the returned function will try to execute and return either the results or false on error. Default is false.
+       */
+
+       create: function(options){
+               var fn = this;
+               options = $merge({
+                       'bind': fn,
+                       'event': false,
+                       'arguments': null,
+                       'delay': false,
+                       'periodical': false,
+                       'attempt': false
+               }, options);
+               if ($chk(options.arguments) && $type(options.arguments) != 'array') options.arguments = [options.arguments];
+               return function(event){
+                       var args;
+                       if (options.event){
+                               event = event || window.event;
+                               args = [(options.event === true) ? event : new options.event(event)];
+                               if (options.arguments) args.extend(options.arguments);
+                       }
+                       else args = options.arguments || arguments;
+                       var returns = function(){
+                               return fn.apply($pick(options.bind, fn), args);
+                       };
+                       if (options.delay) return setTimeout(returns, options.delay);
+                       if (options.periodical) return setInterval(returns, options.periodical);
+                       if (options.attempt) try {return returns();} catch(err){return false;};
+                       return returns();
+               };
+       },
+
+       /*
+       Property: pass
+               Shortcut to create closures with arguments and bind.
+
+       Returns:
+               a function.
+
+       Arguments:
+               args - the arguments passed. must be an array if arguments > 1
+               bind - optional, the object that the "this" of the function will refer to.
+
+       Example:
+               >myFunction.pass([arg1, arg2], myElement);
+       */
+
+       pass: function(args, bind){
+               return this.create({'arguments': args, 'bind': bind});
+       },
+
+       /*
+       Property: attempt
+               Tries to execute the function, returns either the result of the function or false on error.
+
+       Arguments:
+               args - the arguments passed. must be an array if arguments > 1
+               bind - optional, the object that the "this" of the function will refer to.
+
+       Example:
+               >myFunction.attempt([arg1, arg2], myElement);
+       */
+
+       attempt: function(args, bind){
+               return this.create({'arguments': args, 'bind': bind, 'attempt': true})();
+       },
+
+       /*
+       Property: bind
+               method to easily create closures with "this" altered.
+
+       Arguments:
+               bind - optional, the object that the "this" of the function will refer to.
+               args - optional, the arguments passed. must be an array if arguments > 1
+
+       Returns:
+               a function.
+
+       Example:
+               >function myFunction(){
+               >       this.setStyle('color', 'red');
+               >       // note that 'this' here refers to myFunction, not an element
+               >       // we'll need to bind this function to the element we want to alter
+               >};
+               >var myBoundFunction = myFunction.bind(myElement);
+               >myBoundFunction(); // this will make the element myElement red.
+       */
+
+       bind: function(bind, args){
+               return this.create({'bind': bind, 'arguments': args});
+       },
+
+       /*
+       Property: bindAsEventListener
+               cross browser method to pass event firer
+
+       Arguments:
+               bind - optional, the object that the "this" of the function will refer to.
+               args - optional, the arguments passed. must be an array if arguments > 1
+
+       Returns:
+               a function with the parameter bind as its "this" and as a pre-passed argument event or window.event, depending on the browser.
+
+       Example:
+               >function myFunction(event){
+               >       alert(event.clientx) //returns the coordinates of the mouse..
+               >};
+               >myElement.onclick = myFunction.bindAsEventListener(myElement);
+       */
+
+       bindAsEventListener: function(bind, args){
+               return this.create({'bind': bind, 'event': true, 'arguments': args});
+       },
+
+       /*
+       Property: delay
+               Delays the execution of a function by a specified duration.
+
+       Arguments:
+               delay - the duration to wait in milliseconds.
+               bind - optional, the object that the "this" of the function will refer to.
+               args - optional, the arguments passed. must be an array if arguments > 1
+
+       Example:
+               >myFunction.delay(50, myElement) //wait 50 milliseconds, then call myFunction and bind myElement to it
+               >(function(){alert('one second later...')}).delay(1000); //wait a second and alert
+       */
+
+       delay: function(delay, bind, args){
+               return this.create({'delay': delay, 'bind': bind, 'arguments': args})();
+       },
+
+       /*
+       Property: periodical
+               Executes a function in the specified intervals of time
+
+       Arguments:
+               interval - the duration of the intervals between executions.
+               bind - optional, the object that the "this" of the function will refer to.
+               args - optional, the arguments passed. must be an array if arguments > 1
+       */
+
+       periodical: function(interval, bind, args){
+               return this.create({'periodical': interval, 'bind': bind, 'arguments': args})();
+       }
+
+});
+
+/*
+Script: Number.js
+       Contains the Number prototypes.
+
+License:
+       MIT-style license.
+*/
+
+/*
+Class: Number
+       A collection of The Number Object prototype methods.
+*/
+
+Number.extend({
+
+       /*
+       Property: toInt
+               Returns this number; useful because toInt must work on both Strings and Numbers.
+       */
+
+       toInt: function(){
+               return parseInt(this);
+       },
+
+       /*
+       Property: toFloat
+               Returns this number as a float; useful because toFloat must work on both Strings and Numbers.
+       */
+
+       toFloat: function(){
+               return parseFloat(this);
+       },
+
+       /*
+       Property: limit
+               Limits the number.
+
+       Arguments:
+               min - number, minimum value
+               max - number, maximum value
+
+       Returns:
+               the number in the given limits.
+
+       Example:
+               >(12).limit(2, 6.5)  // returns 6.5
+               >(-4).limit(2, 6.5)  // returns 2
+               >(4.3).limit(2, 6.5) // returns 4.3
+       */
+
+       limit: function(min, max){
+               return Math.min(max, Math.max(min, this));
+       },
+
+       /*
+       Property: round
+               Returns the number rounded to specified precision.
+
+       Arguments:
+               precision - integer, number of digits after the decimal point. Can also be negative or zero (default).
+
+       Example:
+               >12.45.round() // returns 12
+               >12.45.round(1) // returns 12.5
+               >12.45.round(-1) // returns 10
+
+       Returns:
+               The rounded number.
+       */
+
+       round: function(precision){
+               precision = Math.pow(10, precision || 0);
+               return Math.round(this * precision) / precision;
+       },
+
+       /*
+       Property: times
+               Executes a passed in function the specified number of times
+
+       Arguments:
+               function - the function to be executed on each iteration of the loop
+
+       Example:
+               >(4).times(alert);
+       */
+
+       times: function(fn){
+               for (var i = 0; i < this; i++) fn(i);
+       }
+
+});
+
+/*
+Script: Element.js
+       Contains useful Element prototypes, to be used with the dollar function <$>.
+
+License:
+       MIT-style license.
+
+Credits:
+       - Some functions are inspired by those found in prototype.js <http://prototype.conio.net/> (c) 2005 Sam Stephenson sam [at] conio [dot] net, MIT-style license
+*/
+
+/*
+Class: Element
+       Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
+*/
+
+var Element = new Class({
+
+       /*
+       Property: initialize
+               Creates a new element of the type passed in.
+
+       Arguments:
+               el - string; the tag name for the element you wish to create. you can also pass in an element reference, in which case it will be extended.
+               props - object; the properties you want to add to your element.
+               Accepts the same keys as <Element.setProperties>, but also allows events and styles
+
+       Props:
+               the key styles will be used as setStyles, the key events will be used as addEvents. any other key is used as setProperty.
+
+       Example:
+               (start code)
+               new Element('a', {
+                       'styles': {
+                               'display': 'block',
+                               'border': '1px solid black'
+                       },
+                       'events': {
+                               'click': function(){
+                                       //aaa
+                               },
+                               'mousedown': function(){
+                                       //aaa
+                               }
+                       },
+                       'class': 'myClassSuperClass',
+                       'href': 'http://mad4milk.net'
+               });
+
+               (end)
+       */
+
+       initialize: function(el, props){
+               if ($type(el) == 'string'){
+                       if (window.ie && props && (props.name || props.type)){
+                               var name = (props.name) ? ' name="' + props.name + '"' : '';
+                               var type = (props.type) ? ' type="' + props.type + '"' : '';
+                               delete props.name;
+                               delete props.type;
+                               el = '<' + el + name + type + '>';
+                       }
+                       el = document.createElement(el);
+               }
+               el = $(el);
+               return (!props || !el) ? el : el.set(props);
+       }
+
+});
+
+/*
+Class: Elements
+       - Every dom function such as <$$>, or in general every function that returns a collection of nodes in mootools, returns them as an Elements class.
+       - The purpose of the Elements class is to allow <Element> methods to work also on <Elements> array.
+       - Elements is also an Array, so it accepts all the <Array> methods.
+       - Every node of the Elements instance is already extended with <$>.
+
+Example:
+       >$$('myselector').each(function(el){
+       > //...
+       >});
+
+       some iterations here, $$('myselector') is also an array.
+
+       >$$('myselector').setStyle('color', 'red');
+       every element returned by $$('myselector') also accepts <Element> methods, in this example every element will be made red.
+*/
+
+var Elements = new Class({
+
+       initialize: function(elements){
+               return (elements) ? $extend(elements, this) : this;
+       }
+
+});
+
+Elements.extend = function(props){
+       for (var prop in props){
+               this.prototype[prop] = props[prop];
+               this[prop] = $native.generic(prop);
+       }
+};
+
+/*
+Section: Utility Functions
+
+Function: $
+       returns the element passed in with all the Element prototypes applied.
+
+Arguments:
+       el - a reference to an actual element or a string representing the id of an element
+
+Example:
+       >$('myElement') // gets a DOM element by id with all the Element prototypes applied.
+       >var div = document.getElementById('myElement');
+       >$(div) //returns an Element also with all the mootools extentions applied.
+
+       You'll use this when you aren't sure if a variable is an actual element or an id, as
+       well as just shorthand for document.getElementById().
+
+Returns:
+       a DOM element or false (if no id was found).
+
+Note:
+       you need to call $ on an element only once to get all the prototypes.
+       But its no harm to call it multiple times, as it will detect if it has been already extended.
+*/
+
+function $(el){
+       if (!el) return null;
+       if (el.htmlElement) return Garbage.collect(el);
+       if ([window, document].contains(el)) return el;
+       var type = $type(el);
+       if (type == 'string'){
+               el = document.getElementById(el);
+               type = (el) ? 'element' : false;
+       }
+       if (type != 'element') return null;
+       if (el.htmlElement) return Garbage.collect(el);
+       if (['object', 'embed'].contains(el.tagName.toLowerCase())) return el;
+       $extend(el, Element.prototype);
+       el.htmlElement = function(){};
+       return Garbage.collect(el);
+};
+
+/*
+Function: $$
+       Selects, and extends DOM elements. Elements arrays returned with $$ will also accept all the <Element> methods.
+       The return type of element methods run through $$ is always an array. If the return array is only made by elements,
+       $$ will be applied automatically.
+
+Arguments:
+       HTML Collections, arrays of elements, arrays of strings as element ids, elements, strings as selectors.
+       Any number of the above as arguments are accepted.
+
+Note:
+       if you load <Element.Selectors.js>, $$ will also accept CSS Selectors, otherwise the only selectors supported are tag names.
+
+Example:
+       >$$('a') //an array of all anchor tags on the page
+       >$$('a', 'b') //an array of all anchor and bold tags on the page
+       >$$('#myElement') //array containing only the element with id = myElement. (only with <Element.Selectors.js>)
+       >$$('#myElement a.myClass') //an array of all anchor tags with the class "myClass"
+       >//within the DOM element with id "myElement" (only with <Element.Selectors.js>)
+       >$$(myelement, myelement2, 'a', ['myid', myid2, 'myid3'], document.getElementsByTagName('div')) //an array containing:
+       >// the element referenced as myelement if existing,
+       >// the element referenced as myelement2 if existing,
+       >// all the elements with a as tag in the page,
+       >// the element with id = myid if existing
+       >// the element with id = myid2 if existing
+       >// the element with id = myid3 if existing
+       >// all the elements with div as tag in the page
+
+Returns:
+       array - array of all the dom elements matched, extended with <$>.  Returns as <Elements>.
+*/
+
+document.getElementsBySelector = document.getElementsByTagName;
+
+function $$(){
+       var elements = [];
+       for (var i = 0, j = arguments.length; i < j; i++){
+               var selector = arguments[i];
+               switch($type(selector)){
+                       case 'element': elements.push(selector);
+                       case 'boolean': break;
+                       case false: break;
+                       case 'string': selector = document.getElementsBySelector(selector, true);
+                       default: elements.extend(selector);
+               }
+       }
+       return $$.unique(elements);
+};
+
+$$.unique = function(array){
+       var elements = [];
+       for (var i = 0, l = array.length; i < l; i++){
+               if (array[i].$included) continue;
+               var element = $(array[i]);
+               if (element && !element.$included){
+                       element.$included = true;
+                       elements.push(element);
+               }
+       }
+       for (var n = 0, d = elements.length; n < d; n++) elements[n].$included = null;
+       return new Elements(elements);
+};
+
+Elements.Multi = function(property){
+       return function(){
+               var args = arguments;
+               var items = [];
+               var elements = true;
+               for (var i = 0, j = this.length, returns; i < j; i++){
+                       returns = this[i][property].apply(this[i], args);
+                       if ($type(returns) != 'element') elements = false;
+                       items.push(returns);
+               };
+               return (elements) ? $$.unique(items) : items;
+       };
+};
+
+Element.extend = function(properties){
+       for (var property in properties){
+               HTMLElement.prototype[property] = properties[property];
+               Element.prototype[property] = properties[property];
+               Element[property] = $native.generic(property);
+               var elementsProperty = (Array.prototype[property]) ? property + 'Elements' : property;
+               Elements.prototype[elementsProperty] = Elements.Multi(property);
+       }
+};
+
+/*
+Class: Element
+       Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
+*/
+
+Element.extend({
+
+       /*
+       Property: set
+               you can set events, styles and properties with this shortcut. same as calling new Element.
+       */
+
+       set: function(props){
+               for (var prop in props){
+                       var val = props[prop];
+                       switch(prop){
+                               case 'styles': this.setStyles(val); break;
+                               case 'events': if (this.addEvents) this.addEvents(val); break;
+                               case 'properties': this.setProperties(val); break;
+                               default: this.setProperty(prop, val);
+                       }
+               }
+               return this;
+       },
+
+       inject: function(el, where){
+               el = $(el);
+               switch(where){
+                       case 'before': el.parentNode.insertBefore(this, el); break;
+                       case 'after':
+                               var next = el.getNext();
+                               if (!next) el.parentNode.appendChild(this);
+                               else el.parentNode.insertBefore(this, next);
+                               break;
+                       case 'top':
+                               var first = el.firstChild;
+                               if (first){
+                                       el.insertBefore(this, first);
+                                       break;
+                               }
+                       default: el.appendChild(this);
+               }
+               return this;
+       },
+
+       /*
+       Property: injectBefore
+               Inserts the Element before the passed element.
+
+       Arguments:
+               el - an element reference or the id of the element to be injected in.
+
+       Example:
+               >html:
+               ><div id="myElement"></div>
+               ><div id="mySecondElement"></div>
+               >js:
+               >$('mySecondElement').injectBefore('myElement');
+               >resulting html:
+               ><div id="mySecondElement"></div>
+               ><div id="myElement"></div>
+       */
+
+       injectBefore: function(el){
+               return this.inject(el, 'before');
+       },
+
+       /*
+       Property: injectAfter
+               Same as <Element.injectBefore>, but inserts the element after.
+       */
+
+       injectAfter: function(el){
+               return this.inject(el, 'after');
+       },
+
+       /*
+       Property: injectInside
+               Same as <Element.injectBefore>, but inserts the element inside.
+       */
+
+       injectInside: function(el){
+               return this.inject(el, 'bottom');
+       },
+
+       /*
+       Property: injectTop
+               Same as <Element.injectInside>, but inserts the element inside, at the top.
+       */
+
+       injectTop: function(el){
+               return this.inject(el, 'top');
+       },
+
+       /*
+       Property: adopt
+               Inserts the passed elements inside the Element.
+
+       Arguments:
+               accepts elements references, element ids as string, selectors ($$('stuff')) / array of elements, array of ids as strings and collections.
+       */
+
+       adopt: function(){
+               var elements = [];
+               $each(arguments, function(argument){
+                       elements = elements.concat(argument);
+               });
+               $$(elements).inject(this);
+               return this;
+       },
+
+       /*
+       Property: remove
+               Removes the Element from the DOM.
+
+       Example:
+               >$('myElement').remove() //bye bye
+       */
+
+       remove: function(){
+               return this.parentNode.removeChild(this);
+       },
+
+       /*
+       Property: clone
+               Clones the Element and returns the cloned one.
+
+       Arguments:
+               contents - boolean, when true the Element is cloned with childNodes, default true
+
+       Returns:
+               the cloned element
+
+       Example:
+               >var clone = $('myElement').clone().injectAfter('myElement');
+               >//clones the Element and append the clone after the Element.
+       */
+
+       clone: function(contents){
+               var el = $(this.cloneNode(contents !== false));
+               if (!el.$events) return el;
+               el.$events = {};
+               for (var type in this.$events) el.$events[type] = {
+                       'keys': $A(this.$events[type].keys),
+                       'values': $A(this.$events[type].values)
+               };
+               return el.removeEvents();
+       },
+
+       /*
+       Property: replaceWith
+               Replaces the Element with an element passed.
+
+       Arguments:
+               el - a string representing the element to be injected in (myElementId, or div), or an element reference.
+               If you pass div or another tag, the element will be created.
+
+       Returns:
+               the passed in element
+
+       Example:
+               >$('myOldElement').replaceWith($('myNewElement')); //$('myOldElement') is gone, and $('myNewElement') is in its place.
+       */
+
+       replaceWith: function(el){
+               el = $(el);
+               this.parentNode.replaceChild(el, this);
+               return el;
+       },
+
+       /*
+       Property: appendText
+               Appends text node to a DOM element.
+
+       Arguments:
+               text - the text to append.
+
+       Example:
+               ><div id="myElement">hey</div>
+               >$('myElement').appendText(' howdy'); //myElement innerHTML is now "hey howdy"
+       */
+
+       appendText: function(text){
+               this.appendChild(document.createTextNode(text));
+               return this;
+       },
+
+       /*
+       Property: hasClass
+               Tests the Element to see if it has the passed in className.
+
+       Returns:
+               true - the Element has the class
+               false - it doesn't
+
+       Arguments:
+               className - string; the class name to test.
+
+       Example:
+               ><div id="myElement" class="testClass"></div>
+               >$('myElement').hasClass('testClass'); //returns true
+       */
+
+       hasClass: function(className){
+               return this.className.contains(className, ' ');
+       },
+
+       /*
+       Property: addClass
+               Adds the passed in class to the Element, if the element doesnt already have it.
+
+       Arguments:
+               className - string; the class name to add
+
+       Example:
+               ><div id="myElement" class="testClass"></div>
+               >$('myElement').addClass('newClass'); //<div id="myElement" class="testClass newClass"></div>
+       */
+
+       addClass: function(className){
+               if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
+               return this;
+       },
+
+       /*
+       Property: removeClass
+               Works like <Element.addClass>, but removes the class from the element.
+       */
+
+       removeClass: function(className){
+               this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1').clean();
+               return this;
+       },
+
+       /*
+       Property: toggleClass
+               Adds or removes the passed in class name to the element, depending on if it's present or not.
+
+       Arguments:
+               className - the class to add or remove
+
+       Example:
+               ><div id="myElement" class="myClass"></div>
+               >$('myElement').toggleClass('myClass');
+               ><div id="myElement" class=""></div>
+               >$('myElement').toggleClass('myClass');
+               ><div id="myElement" class="myClass"></div>
+       */
+
+       toggleClass: function(className){
+               return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
+       },
+
+       /*
+       Property: setStyle
+               Sets a css property to the Element.
+
+               Arguments:
+                       property - the property to set
+                       value - the value to which to set it; for numeric values that require "px" you can pass an integer
+
+               Example:
+                       >$('myElement').setStyle('width', '300px'); //the width is now 300px
+                       >$('myElement').setStyle('width', 300); //the width is now 300px
+       */
+
+       setStyle: function(property, value){
+               switch(property){
+                       case 'opacity': return this.setOpacity(parseFloat(value));
+                       case 'float': property = (window.ie) ? 'styleFloat' : 'cssFloat';
+               }
+               property = property.camelCase();
+               switch($type(value)){
+                       case 'number': if (!['zIndex', 'zoom'].contains(property)) value += 'px'; break;
+                       case 'array': value = 'rgb(' + value.join(',') + ')';
+               }
+               this.style[property] = value;
+               return this;
+       },
+
+       /*
+       Property: setStyles
+               Applies a collection of styles to the Element.
+
+       Arguments:
+               source - an object or string containing all the styles to apply. When its a string it overrides old style.
+
+       Examples:
+               >$('myElement').setStyles({
+               >       border: '1px solid #000',
+               >       width: 300,
+               >       height: 400
+               >});
+
+               OR
+
+               >$('myElement').setStyles('border: 1px solid #000; width: 300px; height: 400px;');
+       */
+
+       setStyles: function(source){
+               switch($type(source)){
+                       case 'object': Element.setMany(this, 'setStyle', source); break;
+                       case 'string': this.style.cssText = source;
+               }
+               return this;
+       },
+
+       /*
+       Property: setOpacity
+               Sets the opacity of the Element, and sets also visibility == "hidden" if opacity == 0, and visibility = "visible" if opacity > 0.
+
+       Arguments:
+               opacity - float; Accepts values from 0 to 1.
+
+       Example:
+               >$('myElement').setOpacity(0.5) //make it 50% transparent
+       */
+
+       setOpacity: function(opacity){
+               if (opacity == 0){
+                       if (this.style.visibility != "hidden") this.style.visibility = "hidden";
+               } else {
+                       if (this.style.visibility != "visible") this.style.visibility = "visible";
+               }
+               if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1;
+               if (window.ie) this.style.filter = (opacity == 1) ? '' : "alpha(opacity=" + opacity * 100 + ")";
+               this.style.opacity = this.$tmp.opacity = opacity;
+               return this;
+       },
+
+       /*
+       Property: getStyle
+               Returns the style of the Element given the property passed in.
+
+       Arguments:
+               property - the css style property you want to retrieve
+
+       Example:
+               >$('myElement').getStyle('width'); //returns "400px"
+               >//but you can also use
+               >$('myElement').getStyle('width').toInt(); //returns 400
+
+       Returns:
+               the style as a string
+       */
+
+       getStyle: function(property){
+               property = property.camelCase();
+               var result = this.style[property];
+               if (!$chk(result)){
+                       if (property == 'opacity') return this.$tmp.opacity;
+                       result = [];
+                       for (var style in Element.Styles){
+                               if (property == style){
+                                       Element.Styles[style].each(function(s){
+                                               var style = this.getStyle(s);
+                                               result.push(parseInt(style) ? style : '0px');
+                                       }, this);
+                                       if (property == 'border'){
+                                               var every = result.every(function(bit){
+                                                       return (bit == result[0]);
+                                               });
+                                               return (every) ? result[0] : false;
+                                       }
+                                       return result.join(' ');
+                               }
+                       }
+                       if (property.contains('border')){
+                               if (Element.Styles.border.contains(property)){
+                                       return ['Width', 'Style', 'Color'].map(function(p){
+                                               return this.getStyle(property + p);
+                                       }, this).join(' ');
+                               } else if (Element.borderShort.contains(property)){
+                                       return ['Top', 'Right', 'Bottom', 'Left'].map(function(p){
+                                               return this.getStyle('border' + p + property.replace('border', ''));
+                                       }, this).join(' ');
+                               }
+                       }
+                       if (document.defaultView) result = document.defaultView.getComputedStyle(this, null).getPropertyValue(property.hyphenate());
+                       else if (this.currentStyle) result = this.currentStyle[property];
+               }
+               if (window.ie) result = Element.fixStyle(property, result, this);
+               if (result && property.test(/color/i) && result.contains('rgb')){
+                       return result.split('rgb').splice(1,4).map(function(color){
+                               return color.rgbToHex();
+                       }).join(' ');
+               }
+               return result;
+       },
+
+       /*
+       Property: getStyles
+               Returns an object of styles of the Element for each argument passed in.
+               Arguments:
+               properties - strings; any number of style properties
+       Example:
+               >$('myElement').getStyles('width','height','padding');
+               >//returns an object like:
+               >{width: "10px", height: "10px", padding: "10px 0px 10px 0px"}
+       */
+
+       getStyles: function(){
+               return Element.getMany(this, 'getStyle', arguments);
+       },
+
+       walk: function(brother, start){
+               brother += 'Sibling';
+               var el = (start) ? this[start] : this[brother];
+               while (el && $type(el) != 'element') el = el[brother];
+               return $(el);
+       },
+
+       /*
+       Property: getPrevious
+               Returns the previousSibling of the Element, excluding text nodes.
+
+       Example:
+               >$('myElement').getPrevious(); //get the previous DOM element from myElement
+
+       Returns:
+               the sibling element or undefined if none found.
+       */
+
+       getPrevious: function(){
+               return this.walk('previous');
+       },
+
+       /*
+       Property: getNext
+               Works as Element.getPrevious, but tries to find the nextSibling.
+       */
+
+       getNext: function(){
+               return this.walk('next');
+       },
+
+       /*
+       Property: getFirst
+               Works as <Element.getPrevious>, but tries to find the firstChild.
+       */
+
+       getFirst: function(){
+               return this.walk('next', 'firstChild');
+       },
+
+       /*
+       Property: getLast
+               Works as <Element.getPrevious>, but tries to find the lastChild.
+       */
+
+       getLast: function(){
+               return this.walk('previous', 'lastChild');
+       },
+
+       /*
+       Property: getParent
+               returns the $(element.parentNode)
+       */
+
+       getParent: function(){
+               return $(this.parentNode);
+       },
+
+       /*
+       Property: getChildren
+               returns all the $(element.childNodes), excluding text nodes. Returns as <Elements>.
+       */
+
+       getChildren: function(){
+               return $$(this.childNodes);
+       },
+
+       /*
+       Property: hasChild
+               returns true if the passed in element is a child of the $(element).
+       */
+
+       hasChild: function(el){
+               return !!$A(this.getElementsByTagName('*')).contains(el);
+       },
+
+       /*
+       Property: getProperty
+               Gets the an attribute of the Element.
+
+       Arguments:
+               property - string; the attribute to retrieve
+
+       Example:
+               >$('myImage').getProperty('src') // returns whatever.gif
+
+       Returns:
+               the value, or an empty string
+       */
+
+       getProperty: function(property){
+               var index = Element.Properties[property];
+               if (index) return this[index];
+               var flag = Element.PropertiesIFlag[property] || 0;
+               if (!window.ie || flag) return this.getAttribute(property, flag);
+               var node = this.attributes[property];
+               return (node) ? node.nodeValue : null;
+       },
+
+       /*
+       Property: removeProperty
+               Removes an attribute from the Element
+
+       Arguments:
+               property - string; the attribute to remove
+       */
+
+       removeProperty: function(property){
+               var index = Element.Properties[property];
+               if (index) this[index] = '';
+               else this.removeAttribute(property);
+               return this;
+       },
+
+       /*
+       Property: getProperties
+               same as <Element.getStyles>, but for properties
+       */
+
+       getProperties: function(){
+               return Element.getMany(this, 'getProperty', arguments);
+       },
+
+       /*
+       Property: setProperty
+               Sets an attribute for the Element.
+
+       Arguments:
+               property - string; the property to assign the value passed in
+               value - the value to assign to the property passed in
+
+       Example:
+               >$('myImage').setProperty('src', 'whatever.gif'); //myImage now points to whatever.gif for its source
+       */
+
+       setProperty: function(property, value){
+               var index = Element.Properties[property];
+               if (index) this[index] = value;
+               else this.setAttribute(property, value);
+               return this;
+       },
+
+       /*
+       Property: setProperties
+               Sets numerous attributes for the Element.
+
+       Arguments:
+               source - an object with key/value pairs.
+
+       Example:
+               (start code)
+               $('myElement').setProperties({
+                       src: 'whatever.gif',
+                       alt: 'whatever dude'
+               });
+               <img src="whatever.gif" alt="whatever dude">
+               (end)
+       */
+
+       setProperties: function(source){
+               return Element.setMany(this, 'setProperty', source);
+       },
+
+       /*
+       Property: setHTML
+               Sets the innerHTML of the Element.
+
+       Arguments:
+               html - string; the new innerHTML for the element.
+
+       Example:
+               >$('myElement').setHTML(newHTML) //the innerHTML of myElement is now = newHTML
+       */
+
+       setHTML: function(){
+               this.innerHTML = $A(arguments).join('');
+               return this;
+       },
+
+       /*
+       Property: setText
+               Sets the inner text of the Element.
+
+       Arguments:
+               text - string; the new text content for the element.
+
+       Example:
+               >$('myElement').setText('some text') //the text of myElement is now = 'some text'
+       */
+
+       setText: function(text){
+               var tag = this.getTag();
+               if (['style', 'script'].contains(tag)){
+                       if (window.ie){
+                               if (tag == 'style') this.styleSheet.cssText = text;
+                               else if (tag ==  'script') this.setProperty('text', text);
+                               return this;
+                       } else {
+                               this.removeChild(this.firstChild);
+                               return this.appendText(text);
+                       }
+               }
+               this[$defined(this.innerText) ? 'innerText' : 'textContent'] = text;
+               return this;
+       },
+
+       /*
+       Property: getText
+               Gets the inner text of the Element.
+       */
+
+       getText: function(){
+               var tag = this.getTag();
+               if (['style', 'script'].contains(tag)){
+                       if (window.ie){
+                               if (tag == 'style') return this.styleSheet.cssText;
+                               else if (tag ==  'script') return this.getProperty('text');
+                       } else {
+                               return this.innerHTML;
+                       }
+               }
+               return ($pick(this.innerText, this.textContent));
+       },
+
+       /*
+       Property: getTag
+               Returns the tagName of the element in lower case.
+
+       Example:
+               >$('myImage').getTag() // returns 'img'
+
+       Returns:
+               The tag name in lower case
+       */
+
+       getTag: function(){
+               return this.tagName.toLowerCase();
+       },
+
+       /*
+       Property: empty
+               Empties an element of all its children.
+
+       Example:
+               >$('myDiv').empty() // empties the Div and returns it
+
+       Returns:
+               The element.
+       */
+
+       empty: function(){
+               Garbage.trash(this.getElementsByTagName('*'));
+               return this.setHTML('');
+       }
+
+});
+
+Element.fixStyle = function(property, result, element){
+       if ($chk(parseInt(result))) return result;
+       if (['height', 'width'].contains(property)){
+               var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'];
+               var size = 0;
+               values.each(function(value){
+                       size += element.getStyle('border-' + value + '-width').toInt() + element.getStyle('padding-' + value).toInt();
+               });
+               return element['offset' + property.capitalize()] - size + 'px';
+       } else if (property.test(/border(.+)Width|margin|padding/)){
+               return '0px';
+       }
+       return result;
+};
+
+Element.Styles = {'border': [], 'padding': [], 'margin': []};
+['Top', 'Right', 'Bottom', 'Left'].each(function(direction){
+       for (var style in Element.Styles) Element.Styles[style].push(style + direction);
+});
+
+Element.borderShort = ['borderWidth', 'borderStyle', 'borderColor'];
+
+Element.getMany = function(el, method, keys){
+       var result = {};
+       $each(keys, function(key){
+               result[key] = el[method](key);
+       });
+       return result;
+};
+
+Element.setMany = function(el, method, pairs){
+       for (var key in pairs) el[method](key, pairs[key]);
+       return el;
+};
+
+Element.Properties = new Abstract({
+       'class': 'className', 'for': 'htmlFor', 'colspan': 'colSpan', 'rowspan': 'rowSpan',
+       'accesskey': 'accessKey', 'tabindex': 'tabIndex', 'maxlength': 'maxLength',
+       'readonly': 'readOnly', 'frameborder': 'frameBorder', 'value': 'value',
+       'disabled': 'disabled', 'checked': 'checked', 'multiple': 'multiple', 'selected': 'selected'
+});
+Element.PropertiesIFlag = {
+       'href': 2, 'src': 2
+};
+
+Element.Methods = {
+       Listeners: {
+               addListener: function(type, fn){
+                       if (this.addEventListener) this.addEventListener(type, fn, false);
+                       else this.attachEvent('on' + type, fn);
+                       return this;
+               },
+
+               removeListener: function(type, fn){
+                       if (this.removeEventListener) this.removeEventListener(type, fn, false);
+                       else this.detachEvent('on' + type, fn);
+                       return this;
+               }
+       }
+};
+
+window.extend(Element.Methods.Listeners);
+document.extend(Element.Methods.Listeners);
+Element.extend(Element.Methods.Listeners);
+
+var Garbage = {
+
+       elements: [],
+
+       collect: function(el){
+               if (!el.$tmp){
+                       Garbage.elements.push(el);
+                       el.$tmp = {'opacity': 1};
+               }
+               return el;
+       },
+
+       trash: function(elements){
+               for (var i = 0, j = elements.length, el; i < j; i++){
+                       if (!(el = elements[i]) || !el.$tmp) continue;
+                       if (el.$events) el.fireEvent('trash').removeEvents();
+                       for (var p in el.$tmp) el.$tmp[p] = null;
+                       for (var d in Element.prototype) el[d] = null;
+                       Garbage.elements[Garbage.elements.indexOf(el)] = null;
+                       el.htmlElement = el.$tmp = el = null;
+               }
+               Garbage.elements.remove(null);
+       },
+
+       empty: function(){
+               Garbage.collect(window);
+               Garbage.collect(document);
+               Garbage.trash(Garbage.elements);
+       }
+
+};
+
+window.addListener('beforeunload', function(){
+       window.addListener('unload', Garbage.empty);
+       if (window.ie) window.addListener('unload', CollectGarbage);
+});
+
+/*
+Script: Element.Event.js
+       Contains the Event Class, Element methods to deal with Element events, custom Events, and the Function prototype bindWithEvent.
+
+License:
+       MIT-style license.
+*/
+
+/*
+Class: Event
+       Cross browser methods to manage events.
+
+Arguments:
+       event - the event
+
+Properties:
+       shift - true if the user pressed the shift
+       control - true if the user pressed the control
+       alt - true if the user pressed the alt
+       meta - true if the user pressed the meta key
+       wheel - the amount of third button scrolling
+       code - the keycode of the key pressed
+       page.x - the x position of the mouse, relative to the full window
+       page.y - the y position of the mouse, relative to the full window
+       client.x - the x position of the mouse, relative to the viewport
+       client.y - the y position of the mouse, relative to the viewport
+       key - the key pressed as a lowercase string. key also returns 'enter', 'up', 'down', 'left', 'right', 'space', 'backspace', 'delete', 'esc'. Handy for these special keys.
+       target - the event target
+       relatedTarget - the event related target
+
+Example:
+       (start code)
+       $('myLink').onkeydown = function(event){
+               var event = new Event(event);
+               //event is now the Event class.
+               alert(event.key); //returns the lowercase letter pressed
+               alert(event.shift); //returns true if the key pressed is shift
+               if (event.key == 's' && event.control) alert('document saved');
+       };
+       (end)
+*/
+
+var Event = new Class({
+
+       initialize: function(event){
+               if (event && event.$extended) return event;
+               this.$extended = true;
+               event = event || window.event;
+               this.event = event;
+               this.type = event.type;
+               this.target = event.target || event.srcElement;
+               if (this.target.nodeType == 3) this.target = this.target.parentNode;
+               this.shift = event.shiftKey;
+               this.control = event.ctrlKey;
+               this.alt = event.altKey;
+               this.meta = event.metaKey;
+               if (['DOMMouseScroll', 'mousewheel'].contains(this.type)){
+                       this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
+               } else if (this.type.contains('key')){
+                       this.code = event.which || event.keyCode;
+                       for (var name in Event.keys){
+                               if (Event.keys[name] == this.code){
+                                       this.key = name;
+                                       break;
+                               }
+                       }
+                       if (this.type == 'keydown'){
+                               var fKey = this.code - 111;
+                               if (fKey > 0 && fKey < 13) this.key = 'f' + fKey;
+                       }
+                       this.key = this.key || String.fromCharCode(this.code).toLowerCase();
+               } else if (this.type.test(/(click|mouse|menu)/)){
+                       this.page = {
+                               'x': event.pageX || event.clientX + document.documentElement.scrollLeft,
+                               'y': event.pageY || event.clientY + document.documentElement.scrollTop
+                       };
+                       this.client = {
+                               'x': event.pageX ? event.pageX - window.pageXOffset : event.clientX,
+                               'y': event.pageY ? event.pageY - window.pageYOffset : event.clientY
+                       };
+                       this.rightClick = (event.which == 3) || (event.button == 2);
+                       switch(this.type){
+                               case 'mouseover': this.relatedTarget = event.relatedTarget || event.fromElement; break;
+                               case 'mouseout': this.relatedTarget = event.relatedTarget || event.toElement;
+                       }
+                       this.fixRelatedTarget();
+               }
+               return this;
+       },
+
+       /*
+       Property: stop
+               cross browser method to stop an event
+       */
+
+       stop: function(){
+               return this.stopPropagation().preventDefault();
+       },
+
+       /*
+       Property: stopPropagation
+               cross browser method to stop the propagation of an event
+       */
+
+       stopPropagation: function(){
+               if (this.event.stopPropagation) this.event.stopPropagation();
+               else this.event.cancelBubble = true;
+               return this;
+       },
+
+       /*
+       Property: preventDefault
+               cross browser method to prevent the default action of the event
+       */
+
+       preventDefault: function(){
+               if (this.event.preventDefault) this.event.preventDefault();
+               else this.event.returnValue = false;
+               return this;
+       }
+
+});
+
+Event.fix = {
+
+       relatedTarget: function(){
+               if (this.relatedTarget && this.relatedTarget.nodeType == 3) this.relatedTarget = this.relatedTarget.parentNode;
+       },
+
+       relatedTargetGecko: function(){
+               try {Event.fix.relatedTarget.call(this);} catch(e){this.relatedTarget = this.target;}
+       }
+
+};
+
+Event.prototype.fixRelatedTarget = (window.gecko) ? Event.fix.relatedTargetGecko : Event.fix.relatedTarget;
+
+/*
+Property: keys
+       you can add additional Event keys codes this way:
+
+Example:
+       (start code)
+       Event.keys.whatever = 80;
+       $(myelement).addEvent(keydown, function(event){
+               event = new Event(event);
+               if (event.key == 'whatever') console.log(whatever key clicked).
+       });
+       (end)
+*/
+
+Event.keys = new Abstract({
+       'enter': 13,
+       'up': 38,
+       'down': 40,
+       'left': 37,
+       'right': 39,
+       'esc': 27,
+       'space': 32,
+       'backspace': 8,
+       'tab': 9,
+       'delete': 46
+});
+
+/*
+Class: Element
+       Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
+*/
+
+Element.Methods.Events = {
+
+       /*
+       Property: addEvent
+               Attaches an event listener to a DOM element.
+
+       Arguments:
+               type - the event to monitor ('click', 'load', etc) without the prefix 'on'.
+               fn - the function to execute
+
+       Example:
+               >$('myElement').addEvent('click', function(){alert('clicked!')});
+       */
+
+       addEvent: function(type, fn){
+               this.$events = this.$events || {};
+               this.$events[type] = this.$events[type] || {'keys': [], 'values': []};
+               if (this.$events[type].keys.contains(fn)) return this;
+               this.$events[type].keys.push(fn);
+               var realType = type;
+               var custom = Element.Events[type];
+               if (custom){
+                       if (custom.add) custom.add.call(this, fn);
+                       if (custom.map) fn = custom.map;
+                       if (custom.type) realType = custom.type;
+               }
+               if (!this.addEventListener) fn = fn.create({'bind': this, 'event': true});
+               this.$events[type].values.push(fn);
+               return (Element.NativeEvents.contains(realType)) ? this.addListener(realType, fn) : this;
+       },
+
+       /*
+       Property: removeEvent
+               Works as Element.addEvent, but instead removes the previously added event listener.
+       */
+
+       removeEvent: function(type, fn){
+               if (!this.$events || !this.$events[type]) return this;
+               var pos = this.$events[type].keys.indexOf(fn);
+               if (pos == -1) return this;
+               var key = this.$events[type].keys.splice(pos,1)[0];
+               var value = this.$events[type].values.splice(pos,1)[0];
+               var custom = Element.Events[type];
+               if (custom){
+                       if (custom.remove) custom.remove.call(this, fn);
+                       if (custom.type) type = custom.type;
+               }
+               return (Element.NativeEvents.contains(type)) ? this.removeListener(type, value) : this;
+       },
+
+       /*
+       Property: addEvents
+               As <addEvent>, but accepts an object and add multiple events at once.
+       */
+
+       addEvents: function(source){
+               return Element.setMany(this, 'addEvent', source);
+       },
+
+       /*
+       Property: removeEvents
+               removes all events of a certain type from an element. if no argument is passed in, removes all events.
+
+       Arguments:
+               type - string; the event name (e.g. 'click')
+       */
+
+       removeEvents: function(type){
+               if (!this.$events) return this;
+               if (!type){
+                       for (var evType in this.$events) this.removeEvents(evType);
+                       this.$events = null;
+               } else if (this.$events[type]){
+                       this.$events[type].keys.each(function(fn){
+                               this.removeEvent(type, fn);
+                       }, this);
+                       this.$events[type] = null;
+               }
+               return this;
+       },
+
+       /*
+       Property: fireEvent
+               executes all events of the specified type present in the element.
+
+       Arguments:
+               type - string; the event name (e.g. 'click')
+               args - array or single object; arguments to pass to the function; if more than one argument, must be an array
+               delay - (integer) delay (in ms) to wait to execute the event
+       */
+
+       fireEvent: function(type, args, delay){
+               if (this.$events && this.$events[type]){
+                       this.$events[type].keys.each(function(fn){
+                               fn.create({'bind': this, 'delay': delay, 'arguments': args})();
+                       }, this);
+               }
+               return this;
+       },
+
+       /*
+       Property: cloneEvents
+               Clones all events from an element to this element.
+
+       Arguments:
+               from - element, copy all events from this element
+               type - optional, copies only events of this type
+       */
+
+       cloneEvents: function(from, type){
+               if (!from.$events) return this;
+               if (!type){
+                       for (var evType in from.$events) this.cloneEvents(from, evType);
+               } else if (from.$events[type]){
+                       from.$events[type].keys.each(function(fn){
+                               this.addEvent(type, fn);
+                       }, this);
+               }
+               return this;
+       }
+
+};
+
+window.extend(Element.Methods.Events);
+document.extend(Element.Methods.Events);
+Element.extend(Element.Methods.Events);
+
+/* Section: Custom Events */
+
+Element.Events = new Abstract({
+
+       /*
+       Event: mouseenter
+               In addition to the standard javascript events (load, mouseover, mouseout, click, etc.) <Event.js> contains two custom events
+               this event fires when the mouse enters the area of the dom element; will not be fired again if the mouse crosses over children of the element (unlike mouseover)
+
+
+       Example:
+               >$(myElement).addEvent('mouseenter', myFunction);
+       */
+
+       'mouseenter': {
+               type: 'mouseover',
+               map: function(event){
+                       event = new Event(event);
+                       if (event.relatedTarget != this && !this.hasChild(event.relatedTarget)) this.fireEvent('mouseenter', event);
+               }
+       },
+
+       /*
+       Event: mouseleave
+               this event fires when the mouse exits the area of the dom element; will not be fired again if the mouse crosses over children of the element (unlike mouseout)
+
+
+       Example:
+               >$(myElement).addEvent('mouseleave', myFunction);
+       */
+
+       'mouseleave': {
+               type: 'mouseout',
+               map: function(event){
+                       event = new Event(event);
+                       if (event.relatedTarget != this && !this.hasChild(event.relatedTarget)) this.fireEvent('mouseleave', event);
+               }
+       },
+
+       'mousewheel': {
+               type: (window.gecko) ? 'DOMMouseScroll' : 'mousewheel'
+       }
+
+});
+
+Element.NativeEvents = [
+       'click', 'dblclick', 'mouseup', 'mousedown', //mouse buttons
+       'mousewheel', 'DOMMouseScroll', //mouse wheel
+       'mouseover', 'mouseout', 'mousemove', //mouse movement
+       'keydown', 'keypress', 'keyup', //keys
+       'load', 'unload', 'beforeunload', 'resize', 'move', //window
+       'focus', 'blur', 'change', 'submit', 'reset', 'select', //forms elements
+       'error', 'abort', 'contextmenu', 'scroll' //misc
+];
+
+/*
+Class: Function
+       A collection of The Function Object prototype methods.
+*/
+
+Function.extend({
+
+       /*
+       Property: bindWithEvent
+               automatically passes MooTools Event Class.
+
+       Arguments:
+               bind - optional, the object that the "this" of the function will refer to.
+               args - optional, an argument to pass to the function; if more than one argument, it must be an array of arguments.
+
+       Returns:
+               a function with the parameter bind as its "this" and as a pre-passed argument event or window.event, depending on the browser.
+
+       Example:
+               >function myFunction(event){
+               >       alert(event.client.x) //returns the coordinates of the mouse..
+               >};
+               >myElement.addEvent('click', myFunction.bindWithEvent(myElement));
+       */
+
+       bindWithEvent: function(bind, args){
+               return this.create({'bind': bind, 'arguments': args, 'event': Event});
+       }
+
+});
+
+
+/*
+Script: Element.Filters.js
+       add Filters capability to <Elements>.
+
+License:
+       MIT-style license.
+*/
+
+/*
+Class: Elements
+       A collection of methods to be used with <$$> elements collections.
+*/
+
+Elements.extend({
+       
+       /*
+       Property: filterByTag
+               Filters the collection by a specified tag name.
+               Returns a new Elements collection, while the original remains untouched.
+       */
+       
+       filterByTag: function(tag){
+               return new Elements(this.filter(function(el){
+                       return (Element.getTag(el) == tag);
+               }));
+       },
+       
+       /*
+       Property: filterByClass
+               Filters the collection by a specified class name.
+               Returns a new Elements collection, while the original remains untouched.
+       */
+       
+       filterByClass: function(className, nocash){
+               var elements = this.filter(function(el){
+                       return (el.className && el.className.contains(className, ' '));
+               });
+               return (nocash) ? elements : new Elements(elements);
+       },
+       
+       /*
+       Property: filterById
+               Filters the collection by a specified ID.
+               Returns a new Elements collection, while the original remains untouched.
+       */
+       
+       filterById: function(id, nocash){
+               var elements = this.filter(function(el){
+                       return (el.id == id);
+               });
+               return (nocash) ? elements : new Elements(elements);
+       },
+       
+       /*
+       Property: filterByAttribute
+               Filters the collection by a specified attribute.
+               Returns a new Elements collection, while the original remains untouched.
+               
+       Arguments:
+               name - the attribute name.
+               operator - optional, the attribute operator.
+               value - optional, the attribute value, only valid if the operator is specified.
+       */
+       
+       filterByAttribute: function(name, operator, value, nocash){
+               var elements = this.filter(function(el){
+                       var current = Element.getProperty(el, name);
+                       if (!current) return false;
+                       if (!operator) return true;
+                       switch(operator){
+                               case '=': return (current == value);
+                               case '*=': return (current.contains(value));
+                               case '^=': return (current.substr(0, value.length) == value);
+                               case '$=': return (current.substr(current.length - value.length) == value);
+                               case '!=': return (current != value);
+                               case '~=': return current.contains(value, ' ');
+                       }
+                       return false;
+               });
+               return (nocash) ? elements : new Elements(elements);
+       }
+
+});
+
+/*
+Script: Element.Selectors.js
+       Css Query related functions and <Element> extensions
+
+License:
+       MIT-style license.
+*/
+
+/* Section: Utility Functions */
+
+/*
+Function: $E
+       Selects a single (i.e. the first found) Element based on the selector passed in and an optional filter element.
+       Returns as <Element>.
+
+Arguments:
+       selector - string; the css selector to match
+       filter - optional; a DOM element to limit the scope of the selector match; defaults to document.
+
+Example:
+       >$E('a', 'myElement') //find the first anchor tag inside the DOM element with id 'myElement'
+
+Returns:
+       a DOM element - the first element that matches the selector
+*/
+
+function $E(selector, filter){
+       return ($(filter) || document).getElement(selector);
+};
+
+/*
+Function: $ES
+       Returns a collection of Elements that match the selector passed in limited to the scope of the optional filter.
+       See Also: <Element.getElements> for an alternate syntax.
+       Returns as <Elements>.
+
+Returns:
+       an array of dom elements that match the selector within the filter
+
+Arguments:
+       selector - string; css selector to match
+       filter - optional; a DOM element to limit the scope of the selector match; defaults to document.
+
+Examples:
+       >$ES("a") //gets all the anchor tags; synonymous with $$("a")
+       >$ES('a','myElement') //get all the anchor tags within $('myElement')
+*/
+
+function $ES(selector, filter){
+       return ($(filter) || document).getElementsBySelector(selector);
+};
+
+$$.shared = {
+
+       'regexp': /^(\w*|\*)(?:#([\w-]+)|\.([\w-]+))?(?:\[(\w+)(?:([!*^$]?=)["']?([^"'\]]*)["']?)?])?$/,
+       
+       'xpath': {
+
+               getParam: function(items, context, param, i){
+                       var temp = [context.namespaceURI ? 'xhtml:' : '', param[1]];
+                       if (param[2]) temp.push('[@id="', param[2], '"]');
+                       if (param[3]) temp.push('[contains(concat(" ", @class, " "), " ', param[3], ' ")]');
+                       if (param[4]){
+                               if (param[5] && param[6]){
+                                       switch(param[5]){
+                                               case '*=': temp.push('[contains(@', param[4], ', "', param[6], '")]'); break;
+                                               case '^=': temp.push('[starts-with(@', param[4], ', "', param[6], '")]'); break;
+                                               case '$=': temp.push('[substring(@', param[4], ', string-length(@', param[4], ') - ', param[6].length, ' + 1) = "', param[6], '"]'); break;
+                                               case '=': temp.push('[@', param[4], '="', param[6], '"]'); break;
+                                               case '!=': temp.push('[@', param[4], '!="', param[6], '"]');
+                                       }
+                               } else {
+                                       temp.push('[@', param[4], ']');
+                               }
+                       }
+                       items.push(temp.join(''));
+                       return items;
+               },
+               
+               getItems: function(items, context, nocash){
+                       var elements = [];
+                       var xpath = document.evaluate('.//' + items.join('//'), context, $$.shared.resolver, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
+                       for (var i = 0, j = xpath.snapshotLength; i < j; i++) elements.push(xpath.snapshotItem(i));
+                       return (nocash) ? elements : new Elements(elements.map($));
+               }
+
+       },
+       
+       'normal': {
+               
+               getParam: function(items, context, param, i){
+                       if (i == 0){
+                               if (param[2]){
+                                       var el = context.getElementById(param[2]);
+                                       if (!el || ((param[1] != '*') && (Element.getTag(el) != param[1]))) return false;
+                                       items = [el];
+                               } else {
+                                       items = $A(context.getElementsByTagName(param[1]));
+                               }
+                       } else {
+                               items = $$.shared.getElementsByTagName(items, param[1]);
+                               if (param[2]) items = Elements.filterById(items, param[2], true);
+                       }
+                       if (param[3]) items = Elements.filterByClass(items, param[3], true);
+                       if (param[4]) items = Elements.filterByAttribute(items, param[4], param[5], param[6], true);
+                       return items;
+               },
+
+               getItems: function(items, context, nocash){
+                       return (nocash) ? items : $$.unique(items);
+               }
+
+       },
+
+       resolver: function(prefix){
+               return (prefix == 'xhtml') ? 'http://www.w3.org/1999/xhtml' : false;
+       },
+
+       getElementsByTagName: function(context, tagName){
+               var found = [];
+               for (var i = 0, j = context.length; i < j; i++) found.extend(context[i].getElementsByTagName(tagName));
+               return found;
+       }
+
+};
+
+$$.shared.method = (window.xpath) ? 'xpath' : 'normal';
+
+/*
+Class: Element
+       Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
+*/
+
+Element.Methods.Dom = {
+
+       /*
+       Property: getElements
+               Gets all the elements within an element that match the given (single) selector.
+               Returns as <Elements>.
+
+       Arguments:
+               selector - string; the css selector to match
+
+       Examples:
+               >$('myElement').getElements('a'); // get all anchors within myElement
+               >$('myElement').getElements('input[name=dialog]') //get all input tags with name 'dialog'
+               >$('myElement').getElements('input[name$=log]') //get all input tags with names ending with 'log'
+
+       Notes:
+               Supports these operators in attribute selectors:
+
+               - = : is equal to
+               - ^= : starts-with
+               - $= : ends-with
+               - != : is not equal to
+
+               Xpath is used automatically for compliant browsers.
+       */
+
+       getElements: function(selector, nocash){
+               var items = [];
+               selector = selector.trim().split(' ');
+               for (var i = 0, j = selector.length; i < j; i++){
+                       var sel = selector[i];
+                       var param = sel.match($$.shared.regexp);
+                       if (!param) break;
+                       param[1] = param[1] || '*';
+                       var temp = $$.shared[$$.shared.method].getParam(items, this, param, i);
+                       if (!temp) break;
+                       items = temp;
+               }
+               return $$.shared[$$.shared.method].getItems(items, this, nocash);
+       },
+
+       /*
+       Property: getElement
+               Same as <Element.getElements>, but returns only the first. Alternate syntax for <$E>, where filter is the Element.
+               Returns as <Element>.
+
+       Arguments:
+               selector - string; css selector
+       */
+
+       getElement: function(selector){
+               return $(this.getElements(selector, true)[0] || false);
+       },
+
+       /*
+       Property: getElementsBySelector
+               Same as <Element.getElements>, but allows for comma separated selectors, as in css. Alternate syntax for <$$>, where filter is the Element.
+               Returns as <Elements>.
+
+       Arguments:
+               selector - string; css selector
+       */
+
+       getElementsBySelector: function(selector, nocash){
+               var elements = [];
+               selector = selector.split(',');
+               for (var i = 0, j = selector.length; i < j; i++) elements = elements.concat(this.getElements(selector[i], true));
+               return (nocash) ? elements : $$.unique(elements);
+       }
+
+};
+
+Element.extend({
+
+       /*
+       Property: getElementById
+               Targets an element with the specified id found inside the Element. Does not overwrite document.getElementById.
+
+       Arguments:
+               id - string; the id of the element to find.
+       */
+
+       getElementById: function(id){
+               var el = document.getElementById(id);
+               if (!el) return false;
+               for (var parent = el.parentNode; parent != this; parent = parent.parentNode){
+                       if (!parent) return false;
+               }
+               return el;
+       }/*compatibility*/,
+       
+       getElementsByClassName: function(className){ 
+               return this.getElements('.' + className); 
+       }
+       
+       /*end compatibility*/
+
+});
+
+document.extend(Element.Methods.Dom);
+Element.extend(Element.Methods.Dom);
+
+/*
+Script: Element.Form.js
+       Contains Element prototypes to deal with Forms and their elements.
+
+License:
+       MIT-style license.
+*/
+
+/*
+Class: Element
+       Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
+*/
+
+Element.extend({
+
+       /*
+       Property: getValue
+               Returns the value of the Element, if its tag is textarea, select or input. getValue called on a multiple select will return an array.
+       */
+
+       getValue: function(){
+               switch(this.getTag()){
+                       case 'select':
+                               var values = [];
+                               $each(this.options, function(option){
+                                       if (option.selected) values.push($pick(option.value, option.text));
+                               });
+                               return (this.multiple) ? values : values[0];
+                       case 'input': if (!(this.checked && ['checkbox', 'radio'].contains(this.type)) && !['hidden', 'text', 'password'].contains(this.type)) break;
+                       case 'textarea': return this.value;
+               }
+               return false;
+       },
+
+       getFormElements: function(){
+               return $$(this.getElementsByTagName('input'), this.getElementsByTagName('select'), this.getElementsByTagName('textarea'));
+       },
+
+       /*
+       Property: toQueryString
+               Reads the children inputs of the Element and generates a query string, based on their values. Used internally in <Ajax>
+
+       Example:
+               (start code)
+               <form id="myForm" action="submit.php">
+               <input name="email" value="bob@bob.com">
+               <input name="zipCode" value="90210">
+               </form>
+
+               <script>
+                $('myForm').toQueryString()
+               </script>
+               (end)
+
+               Returns:
+                       email=bob@bob.com&zipCode=90210
+       */
+
+       toQueryString: function(){
+               var queryString = [];
+               this.getFormElements().each(function(el){
+                       var name = el.name;
+                       var value = el.getValue();
+                       if (value === false || !name || el.disabled) return;
+                       var qs = function(val){
+                               queryString.push(name + '=' + encodeURIComponent(val));
+                       };
+                       if ($type(value) == 'array') value.each(qs);
+                       else qs(value);
+               });
+               return queryString.join('&');
+       }
+
+});
+
+/*
+Script: Element.Dimensions.js
+       Contains Element prototypes to deal with Element size and position in space.
+
+Note:
+       The functions in this script require n XHTML doctype.
+
+License:
+       MIT-style license.
+*/
+
+/*
+Class: Element
+       Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
+*/
+
+Element.extend({
+
+       /*
+       Property: scrollTo
+               Scrolls the element to the specified coordinated (if the element has an overflow)
+
+       Arguments:
+               x - the x coordinate
+               y - the y coordinate
+
+       Example:
+               >$('myElement').scrollTo(0, 100)
+       */
+
+       scrollTo: function(x, y){
+               this.scrollLeft = x;
+               this.scrollTop = y;
+       },
+
+       /*
+       Property: getSize
+               Return an Object representing the size/scroll values of the element.
+
+       Example:
+               (start code)
+               $('myElement').getSize();
+               (end)
+
+       Returns:
+               (start code)
+               {
+                       'scroll': {'x': 100, 'y': 100},
+                       'size': {'x': 200, 'y': 400},
+                       'scrollSize': {'x': 300, 'y': 500}
+               }
+               (end)
+       */
+
+       getSize: function(){
+               return {
+                       'scroll': {'x': this.scrollLeft, 'y': this.scrollTop},
+                       'size': {'x': this.offsetWidth, 'y': this.offsetHeight},
+                       'scrollSize': {'x': this.scrollWidth, 'y': this.scrollHeight}
+               };
+       },
+
+       /*
+       Property: getPosition
+               Returns the real offsets of the element.
+
+       Arguments:
+               overflown - optional, an array of nested scrolling containers for scroll offset calculation, use this if your element is inside any element containing scrollbars
+
+       Example:
+               >$('element').getPosition();
+
+       Returns:
+               >{x: 100, y:500};
+       */
+
+       getPosition: function(overflown){
+               overflown = overflown || [];
+               var el = this, left = 0, top = 0;
+               do {
+                       left += el.offsetLeft || 0;
+                       top += el.offsetTop || 0;
+                       el = el.offsetParent;
+               } while (el);
+               overflown.each(function(element){
+                       left -= element.scrollLeft || 0;
+                       top -= element.scrollTop || 0;
+               });
+               return {'x': left, 'y': top};
+       },
+
+       /*
+       Property: getTop
+               Returns the distance from the top of the window to the Element.
+
+       Arguments:
+               overflown - optional, an array of nested scrolling containers, see Element::getPosition
+       */
+
+       getTop: function(overflown){
+               return this.getPosition(overflown).y;
+       },
+
+       /*
+       Property: getLeft
+               Returns the distance from the left of the window to the Element.
+
+       Arguments:
+               overflown - optional, an array of nested scrolling containers, see Element::getPosition
+       */
+
+       getLeft: function(overflown){
+               return this.getPosition(overflown).x;
+       },
+
+       /*
+       Property: getCoordinates
+               Returns an object with width, height, left, right, top, and bottom, representing the values of the Element
+
+       Arguments:
+               overflown - optional, an array of nested scrolling containers, see Element::getPosition
+
+       Example:
+               (start code)
+               var myValues = $('myElement').getCoordinates();
+               (end)
+
+       Returns:
+               (start code)
+               {
+                       width: 200,
+                       height: 300,
+                       left: 100,
+                       top: 50,
+                       right: 300,
+                       bottom: 350
+               }
+               (end)
+       */
+
+       getCoordinates: function(overflown){
+               var position = this.getPosition(overflown);
+               var obj = {
+                       'width': this.offsetWidth,
+                       'height': this.offsetHeight,
+                       'left': position.x,
+                       'top': position.y
+               };
+               obj.right = obj.left + obj.width;
+               obj.bottom = obj.top + obj.height;
+               return obj;
+       }
+
+});
+
+/*
+Script: Window.DomReady.js
+       Contains the custom event domready, for window.
+
+License:
+       MIT-style license.
+*/
+
+/* Section: Custom Events */
+
+/*
+Event: domready
+       executes a function when the dom tree is loaded, without waiting for images. Only works when called from window.
+
+Credits:
+       (c) Dean Edwards/Matthias Miller/John Resig, remastered for MooTools.
+
+Arguments:
+       fn - the function to execute when the DOM is ready
+
+Example:
+       > window.addEvent('domready', function(){
+       >       alert('the dom is ready');
+       > });
+*/
+
+Element.Events.domready = {
+
+       add: function(fn){
+               if (window.loaded){
+                       fn.call(this);
+                       return;
+               }
+               var domReady = function(){
+                       if (window.loaded) return;
+                       window.loaded = true;
+                       window.timer = $clear(window.timer);
+                       this.fireEvent('domready');
+               }.bind(this);
+               if (document.readyState && window.webkit){
+                       window.timer = function(){
+                               if (['loaded','complete'].contains(document.readyState)) domReady();
+                       }.periodical(50);
+               } else if (document.readyState && window.ie){
+                       if (!$('ie_ready')){
+                               var src = (window.location.protocol == 'https:') ? '://0' : 'javascript:void(0)';
+                               document.write('<script id="ie_ready" defer src="' + src + '"><\/script>');
+                               $('ie_ready').onreadystatechange = function(){
+                                       if (this.readyState == 'complete') domReady();
+                               };
+                       }
+               } else {
+                       window.addListener("load", domReady);
+                       document.addListener("DOMContentLoaded", domReady);
+               }
+       }
+
+};
+
+/*compatibility*/
+
+window.onDomReady = function(fn){ 
+       return this.addEvent('domready', fn); 
+};
+
+/*end compatibility*/
+
+/*
+Script: Window.Size.js
+       Window cross-browser dimensions methods.
+       
+Note:
+       The Functions in this script require an XHTML doctype.
+
+License:
+       MIT-style license.
+*/
+
+/*
+Class: window
+       Cross browser methods to get various window dimensions.
+       Warning: All these methods require that the browser operates in strict mode, not quirks mode.
+*/
+
+window.extend({
+
+       /*
+       Property: getWidth
+               Returns an integer representing the width of the browser window (without the scrollbar).
+       */
+
+       getWidth: function(){
+               if (this.webkit419) return this.innerWidth;
+               if (this.opera) return document.body.clientWidth;
+               return document.documentElement.clientWidth;
+       },
+
+       /*
+       Property: getHeight
+               Returns an integer representing the height of the browser window (without the scrollbar).
+       */
+
+       getHeight: function(){
+               if (this.webkit419) return this.innerHeight;
+               if (this.opera) return document.body.clientHeight;
+               return document.documentElement.clientHeight;
+       },
+
+       /*
+       Property: getScrollWidth
+               Returns an integer representing the scrollWidth of the window.
+               This value is equal to or bigger than <getWidth>.
+
+       See Also:
+               <http://developer.mozilla.org/en/docs/DOM:element.scrollWidth>
+       */
+
+       getScrollWidth: function(){
+               if (this.ie) return Math.max(document.documentElement.offsetWidth, document.documentElement.scrollWidth);
+               if (this.webkit) return document.body.scrollWidth;
+               return document.documentElement.scrollWidth;
+       },
+
+       /*
+       Property: getScrollHeight
+               Returns an integer representing the scrollHeight of the window.
+               This value is equal to or bigger than <getHeight>.
+
+       See Also:
+               <http://developer.mozilla.org/en/docs/DOM:element.scrollHeight>
+       */
+
+       getScrollHeight: function(){
+               if (this.ie) return Math.max(document.documentElement.offsetHeight, document.documentElement.scrollHeight);
+               if (this.webkit) return document.body.scrollHeight;
+               return document.documentElement.scrollHeight;
+       },
+
+       /*
+       Property: getScrollLeft
+               Returns an integer representing the scrollLeft of the window (the number of pixels the window has scrolled from the left).
+
+       See Also:
+               <http://developer.mozilla.org/en/docs/DOM:element.scrollLeft>
+       */
+
+       getScrollLeft: function(){
+               return this.pageXOffset || document.documentElement.scrollLeft;
+       },
+
+       /*
+       Property: getScrollTop
+               Returns an integer representing the scrollTop of the window (the number of pixels the window has scrolled from the top).
+
+       See Also:
+               <http://developer.mozilla.org/en/docs/DOM:element.scrollTop>
+       */
+
+       getScrollTop: function(){
+               return this.pageYOffset || document.documentElement.scrollTop;
+       },
+
+       /*
+       Property: getSize
+               Same as <Element.getSize>
+       */
+
+       getSize: function(){
+               return {
+                       'size': {'x': this.getWidth(), 'y': this.getHeight()},
+                       'scrollSize': {'x': this.getScrollWidth(), 'y': this.getScrollHeight()},
+                       'scroll': {'x': this.getScrollLeft(), 'y': this.getScrollTop()}
+               };
+       },
+
+       //ignore
+       getPosition: function(){return {'x': 0, 'y': 0};}
+
+});
+
+/*
+Script: Fx.Base.js
+       Contains <Fx.Base>, the foundamentals of the MooTools Effects.
+
+License:
+       MIT-style license.
+*/
+
+var Fx = {};
+
+/*
+Class: Fx.Base
+       Base class for the Effects.
+
+Options:
+       transition - the equation to use for the effect see <Fx.Transitions>; default is <Fx.Transitions.Sine.easeInOut>
+       duration - the duration of the effect in ms; 500 is the default.
+       unit - the unit is 'px' by default (other values include things like 'em' for fonts or '%').
+       wait - boolean: to wait or not to wait for a current transition to end before running another of the same instance. defaults to true.
+       fps - the frames per second for the transition; default is 50
+       
+Events:
+       onStart - the function to execute as the effect begins; nothing (<Class.empty>) by default.
+       onComplete - the function to execute after the effect has processed; nothing (<Class.empty>) by default.
+       onCancel - the function to execute when you manually stop the effect.
+*/
+
+Fx.Base = new Class({
+
+       options: {
+               onStart: Class.empty,
+               onComplete: Class.empty,
+               onCancel: Class.empty,
+               transition: function(p){
+                       return -(Math.cos(Math.PI * p) - 1) / 2;
+               },
+               duration: 500,
+               unit: 'px',
+               wait: true,
+               fps: 50
+       },
+
+       initialize: function(options){
+               this.element = this.element || null;
+               this.setOptions(options);
+               if (this.options.initialize) this.options.initialize.call(this);
+       },
+
+       step: function(){
+               var time = $time();
+               if (time < this.time + this.options.duration){
+                       this.delta = this.options.transition((time - this.time) / this.options.duration);
+                       this.setNow();
+                       this.increase();
+               } else {
+                       this.stop(true);
+                       this.set(this.to);
+                       this.fireEvent('onComplete', this.element, 10);
+                       this.callChain();
+               }
+       },
+
+       /*
+       Property: set
+               Immediately sets the value with no transition.
+
+       Arguments:
+               to - the point to jump to
+
+       Example:
+               >var myFx = new Fx.Style('myElement', 'opacity').set(0); //will make it immediately transparent
+       */
+
+       set: function(to){
+               this.now = to;
+               this.increase();
+               return this;
+       },
+
+       setNow: function(){
+               this.now = this.compute(this.from, this.to);
+       },
+
+       compute: function(from, to){
+               return (to - from) * this.delta + from;
+       },
+
+       /*
+       Property: start
+               Executes an effect from one position to the other.
+
+       Arguments:
+               from - integer: staring value
+               to - integer: the ending value
+
+       Examples:
+               >var myFx = new Fx.Style('myElement', 'opacity').start(0,1); //display a transition from transparent to opaque.
+       */
+
+       start: function(from, to){
+               if (!this.options.wait) this.stop();
+               else if (this.timer) return this;
+               this.from = from;
+               this.to = to;
+               this.change = this.to - this.from;
+               this.time = $time();
+               this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this);
+               this.fireEvent('onStart', this.element);
+               return this;
+       },
+
+       /*
+       Property: stop
+               Stops the transition.
+       */
+
+       stop: function(end){
+               if (!this.timer) return this;
+               this.timer = $clear(this.timer);
+               if (!end) this.fireEvent('onCancel', this.element);
+               return this;
+       }/*compatibility*/,
+       
+       custom: function(from, to){
+               return this.start(from, to);
+       },
+
+       clearTimer: function(end){
+               return this.stop(end);
+       }
+
+       /*end compatibility*/
+
+});
+
+Fx.Base.implement(new Chain, new Events, new Options);
+
+/*
+Script: Fx.CSS.js
+       Css parsing class for effects. Required by <Fx.Style>, <Fx.Styles>, <Fx.Elements>. No documentation needed, as its used internally.
+
+License:
+       MIT-style license.
+*/
+
+Fx.CSS = {
+
+       select: function(property, to){
+               if (property.test(/color/i)) return this.Color;
+               var type = $type(to);
+               if ((type == 'array') || (type == 'string' && to.contains(' '))) return this.Multi;
+               return this.Single;
+       },
+
+       parse: function(el, property, fromTo){
+               if (!fromTo.push) fromTo = [fromTo];
+               var from = fromTo[0], to = fromTo[1];
+               if (!$chk(to)){
+                       to = from;
+                       from = el.getStyle(property);
+               }
+               var css = this.select(property, to);
+               return {'from': css.parse(from), 'to': css.parse(to), 'css': css};
+       }
+
+};
+
+Fx.CSS.Single = {
+
+       parse: function(value){
+               return parseFloat(value);
+       },
+
+       getNow: function(from, to, fx){
+               return fx.compute(from, to);
+       },
+
+       getValue: function(value, unit, property){
+               if (unit == 'px' && property != 'opacity') value = Math.round(value);
+               return value + unit;
+       }
+
+};
+
+Fx.CSS.Multi = {
+
+       parse: function(value){
+               return value.push ? value : value.split(' ').map(function(v){
+                       return parseFloat(v);
+               });
+       },
+
+       getNow: function(from, to, fx){
+               var now = [];
+               for (var i = 0; i < from.length; i++) now[i] = fx.compute(from[i], to[i]);
+               return now;
+       },
+
+       getValue: function(value, unit, property){
+               if (unit == 'px' && property != 'opacity') value = value.map(Math.round);
+               return value.join(unit + ' ') + unit;
+       }
+
+};
+
+Fx.CSS.Color = {
+
+       parse: function(value){
+               return value.push ? value : value.hexToRgb(true);
+       },
+
+       getNow: function(from, to, fx){
+               var now = [];
+               for (var i = 0; i < from.length; i++) now[i] = Math.round(fx.compute(from[i], to[i]));
+               return now;
+       },
+
+       getValue: function(value){
+               return 'rgb(' + value.join(',') + ')';
+       }
+
+};
+
+/*
+Script: Fx.Style.js
+       Contains <Fx.Style>
+
+License:
+       MIT-style license.
+*/
+
+/*
+Class: Fx.Style
+       The Style effect, used to transition any css property from one value to another. Includes colors.
+       Colors must be in hex format.
+       Inherits methods, properties, options and events from <Fx.Base>.
+
+Arguments:
+       el - the $(element) to apply the style transition to
+       property - the property to transition
+       options - the Fx.Base options (see: <Fx.Base>)
+
+Example:
+       >var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500});
+       >marginChange.start(10, 100);
+*/
+
+Fx.Style = Fx.Base.extend({
+
+       initialize: function(el, property, options){
+               this.element = $(el);
+               this.property = property;
+               this.parent(options);
+       },
+
+       /*
+       Property: hide
+               Same as <Fx.Base.set> (0); hides the element immediately without transition.
+       */
+
+       hide: function(){
+               return this.set(0);
+       },
+
+       setNow: function(){
+               this.now = this.css.getNow(this.from, this.to, this);
+       },
+
+       /*
+       Property: set
+               Sets the element's css property (specified at instantiation) to the specified value immediately.
+
+       Example:
+               (start code)
+               var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500});
+               marginChange.set(10); //margin-top is set to 10px immediately
+               (end)
+       */
+
+       set: function(to){
+               this.css = Fx.CSS.select(this.property, to);
+               return this.parent(this.css.parse(to));
+       },
+
+       /*
+       Property: start
+               Displays the transition to the value/values passed in
+
+       Arguments:
+               from - (integer; optional) the starting position for the transition
+               to - (integer) the ending position for the transition
+
+       Note:
+               If you provide only one argument, the transition will use the current css value for its starting value.
+
+       Example:
+               (start code)
+               var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500});
+               marginChange.start(10); //tries to read current margin top value and goes from current to 10
+               (end)
+       */
+
+       start: function(from, to){
+               if (this.timer && this.options.wait) return this;
+               var parsed = Fx.CSS.parse(this.element, this.property, [from, to]);
+               this.css = parsed.css;
+               return this.parent(parsed.from, parsed.to);
+       },
+
+       increase: function(){
+               this.element.setStyle(this.property, this.css.getValue(this.now, this.options.unit, this.property));
+       }
+
+});
+
+/*
+Class: Element
+       Custom class to allow all of its methods to be used with any DOM element via the dollar function <$>.
+*/
+
+Element.extend({
+
+       /*
+       Property: effect
+               Applies an <Fx.Style> to the Element; This a shortcut for <Fx.Style>.
+
+       Arguments:
+               property - (string) the css property to alter
+               options - (object; optional) key/value set of options (see <Fx.Style>)
+
+       Example:
+               >var myEffect = $('myElement').effect('height', {duration: 1000, transition: Fx.Transitions.linear});
+               >myEffect.start(10, 100);
+               >//OR
+               >$('myElement').effect('height', {duration: 1000, transition: Fx.Transitions.linear}).start(10,100);
+       */
+
+       effect: function(property, options){
+               return new Fx.Style(this, property, options);
+       }
+
+});
+
+/*
+Script: Json.js
+       Simple Json parser and Stringyfier, See: <http://www.json.org/>
+
+License:
+       MIT-style license.
+*/
+
+/*
+Class: Json
+       Simple Json parser and Stringyfier, See: <http://www.json.org/>
+*/
+
+var Json = {
+
+       /*
+       Property: toString
+               Converts an object to a string, to be passed in server-side scripts as a parameter. Although its not normal usage for this class, this method can also be used to convert functions and arrays to strings.
+
+       Arguments:
+               obj - the object to convert to string
+
+       Returns:
+               A json string
+
+       Example:
+               (start code)
+               Json.toString({apple: 'red', lemon: 'yellow'}); '{"apple":"red","lemon":"yellow"}'
+               (end)
+       */
+
+       toString: function(obj){
+               switch($type(obj)){
+                       case 'string':
+                               return '"' + obj.replace(/(["\\])/g, '\\$1') + '"';
+                       case 'array':
+                               return '[' + obj.map(Json.toString).join(',') + ']';
+                       case 'object':
+                               var string = [];
+                               for (var property in obj) string.push(Json.toString(property) + ':' + Json.toString(obj[property]));
+                               return '{' + string.join(',') + '}';
+                       case 'number':
+                               if (isFinite(obj)) break;
+                       case false:
+                               return 'null';
+               }
+               return String(obj);
+       },
+
+       /*
+       Property: evaluate
+               converts a json string to an javascript Object.
+
+       Arguments:
+               str - the string to evaluate. if its not a string, it returns false.
+               secure - optionally, performs syntax check on json string. Defaults to false.
+
+       Credits:
+               Json test regexp is by Douglas Crockford <http://crockford.org>.
+
+       Example:
+               >var myObject = Json.evaluate('{"apple":"red","lemon":"yellow"}');
+               >//myObject will become {apple: 'red', lemon: 'yellow'}
+       */
+
+       evaluate: function(str, secure){
+               return (($type(str) != 'string') || (secure && !str.test(/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/))) ? null : eval('(' + str + ')');
+       }
+
+};
+
+/*\r
+Script: Hash.js\r
+       Contains the class Hash.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+/*\r
+Class: Hash\r
+       It wraps an object that it uses internally as a map. The user must use set(), get(), and remove() to add/change, retrieve and remove values, it must not access the internal object directly. null/undefined values are allowed.\r
+\r
+Note:\r
+       Each hash instance has the length property.\r
+\r
+Arguments:\r
+       obj - an object to convert into a Hash instance.\r
+\r
+Example:\r
+       (start code)\r
+       var hash = new Hash({a: 'hi', b: 'world', c: 'howdy'});\r
+       hash.remove('b'); // b is removed.\r
+       hash.set('c', 'hello');\r
+       hash.get('c'); // returns 'hello'\r
+       hash.length // returns 2 (a and c)\r
+       (end)\r
+*/\r
+\r
+var Hash = new Class({\r
+\r
+       length: 0,\r
+\r
+       initialize: function(object){\r
+               this.obj = object || {};\r
+               this.setLength();\r
+       },\r
+\r
+       /*\r
+       Property: get\r
+               Retrieves a value from the hash.\r
+\r
+       Arguments:\r
+               key - The key\r
+\r
+       Returns:\r
+               The value\r
+       */\r
+\r
+       get: function(key){\r
+               return (this.hasKey(key)) ? this.obj[key] : null;\r
+       },\r
+\r
+       /*\r
+       Property: hasKey\r
+               Check the presence of a specified key-value pair in the hash.\r
+\r
+       Arguments:\r
+               key - The key\r
+\r
+       Returns:\r
+               True if the Hash contains a value for the specified key, otherwise false\r
+       */\r
+\r
+       hasKey: function(key){\r
+               return (key in this.obj);\r
+       },\r
+\r
+       /*\r
+       Property: set\r
+               Adds a key-value pair to the hash or replaces a previous value associated with the key.\r
+\r
+       Arguments:\r
+               key - The key\r
+               value - The value\r
+       */\r
+\r
+       set: function(key, value){\r
+               if (!this.hasKey(key)) this.length++;\r
+               this.obj[key] = value;\r
+               return this;\r
+       },\r
+\r
+       setLength: function(){\r
+               this.length = 0;\r
+               for (var p in this.obj) this.length++;\r
+               return this;\r
+       },\r
+\r
+       /*\r
+       Property: remove\r
+               Removes a key-value pair from the hash.\r
+\r
+       Arguments:\r
+               key - The key\r
+       */\r
+\r
+       remove: function(key){\r
+               if (this.hasKey(key)){\r
+                       delete this.obj[key];\r
+                       this.length--;\r
+               }\r
+               return this;\r
+       },\r
+\r
+       /*\r
+       Property: each\r
+               Calls a function for each key-value pair. The first argument passed to the function will be the value, the second one will be the key, like $each.\r
+\r
+       Arguments:\r
+               fn - The function to call for each key-value pair\r
+               bind - Optional, the object that will be referred to as "this" in the function\r
+       */\r
+\r
+       each: function(fn, bind){\r
+               $each(this.obj, fn, bind);\r
+       },\r
+\r
+       /*\r
+       Property: extend\r
+               Extends the current hash with an object containing key-value pairs. Values for duplicate keys will be replaced by the new ones.\r
+\r
+       Arguments:\r
+               obj - An object containing key-value pairs\r
+       */\r
+\r
+       extend: function(obj){\r
+               $extend(this.obj, obj);\r
+               return this.setLength();\r
+       },\r
+\r
+       /*\r
+       Property: merge\r
+               Merges the current hash with multiple objects.\r
+       */\r
+\r
+       merge: function(){\r
+               this.obj = $merge.apply(null, [this.obj].extend(arguments));\r
+               return this.setLength();\r
+       },\r
+\r
+       /*\r
+       Property: empty\r
+               Empties all hash values properties and values.\r
+       */\r
+\r
+       empty: function(){\r
+               this.obj = {};\r
+               this.length = 0;\r
+               return this;\r
+       },\r
+\r
+       /*\r
+       Property: keys\r
+               Returns an array containing all the keys, in the same order as the values returned by <Hash.values>.\r
+\r
+       Returns:\r
+               An array containing all the keys of the hash\r
+       */\r
+\r
+       keys: function(){\r
+               var keys = [];\r
+               for (var property in this.obj) keys.push(property);\r
+               return keys;\r
+       },\r
+\r
+       /*\r
+       Property: values\r
+               Returns an array containing all the values, in the same order as the keys returned by <Hash.keys>.\r
+\r
+       Returns:\r
+               An array containing all the values of the hash\r
+       */\r
+\r
+       values: function(){\r
+               var values = [];\r
+               for (var property in this.obj) values.push(this.obj[property]);\r
+               return values;\r
+       }\r
+\r
+});\r
+\r
+/* Section: Utility Functions */\r
+\r
+/*\r
+Function: $H\r
+       Shortcut to create a Hash from an Object.\r
+*/\r
+\r
+function $H(obj){\r
+       return new Hash(obj);\r
+};
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/notice.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/notice.js
new file mode 100644 (file)
index 0000000..c54be8c
--- /dev/null
@@ -0,0 +1,37 @@
+var Notice=new Class({
+       getWrapper:function(){
+               var w=$('notice_wrapper');
+               if(w)return w;
+               w=new Element('div',{
+                       'id':'notice_wrapper',
+                       'styles':{
+                               'position':'absolute',
+                               'top':5,
+                               'right':5,
+                               'z-index':222
+                       }
+               });
+               document.body.appendChild(w);
+               return w;
+       },
+       initialize:function(message){
+               var id=_Notices++;
+               this.id=id;
+               var notice_message=new Element('div',{
+                       'id':'notice_message_'+id,
+                       'class':'notice'
+               });
+               notice_message.setHTML(message);
+               this.getWrapper().appendChild(notice_message);
+               var myFx=new Fx.Style(notice_message,'opacity',{'duration':3500});
+               myFx.start(1,0).chain(function(){
+                       var myFx2=new Fx.Style(notice_message,'height');
+                       myFx2.start(notice_message.offsetHeight-parseInt(notice_message.getStyle('padding-top'))-parseInt(notice_message.getStyle('padding-bottom')),0).chain(function(){
+                               notice_message.remove();
+                               var w=$('notice_wrapper');
+                               if(!w.childNodes.length)w.remove();
+                       });
+               });
+       }
+});
+var _Notices=0;
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/panels.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/panels.js
new file mode 100644 (file)
index 0000000..e86e085
--- /dev/null
@@ -0,0 +1,450 @@
+// see license.txt for licensing
+function kfm_addPanel(wrapper,panel){
+       wrapper=$(wrapper);
+       if(!wrapper)return false;
+       if(kfm_hasPanel(wrapper,panel)){
+               $(panel).visible=1;
+               kfm_refreshPanels(wrapper);
+               return;
+       }
+       if(panel=='kfm_directories_panel'){
+               el=kfm_createPanel(
+                       kfm.lang.Directories,
+                       'kfm_directories_panel',
+                       new Element('table',{
+                               'id':'kfm_directories'
+                       }),
+                       {'state':1,'abilities':-1,'order':1}
+               );
+       }
+       else if(panel=='kfm_directory_properties_panel')el=kfm_createPanel(
+               kfm.lang.DirectoryProperties,
+               'kfm_directory_properties_panel',
+               new Element('div',{
+                       'class':'kfm_directory_properties'
+               }),
+               {state:0,abilities:1}
+       );
+       else if(panel=='kfm_file_details_panel')el=kfm_createFileDetailsPanel();
+       else if(panel=='kfm_file_upload_panel')el=kfm_createFileUploadPanel();
+       else if(panel=='kfm_search_panel')el=kfm_createSearchPanel();
+       else if(panel=='kfm_logs_panel')el=kfm_createPanel(
+               kfm.lang.Logs,
+               'kfm_logs_panel',
+               (new Element('p')).setHTML(kfm.lang.LoadingKFM),
+               {order:100}
+       );
+       else if(panel=='kfm_widgets_panel')el=kfm_createWidgetsPanel();
+       else{
+               kfm_log(kfm.lang.NoPanel(panel));
+               return;
+       }
+       if(!wrapper.panels)wrapper.panels=[];
+       wrapper.panels[wrapper.panels.length]=panel;
+       wrapper.appendChild(el);
+}
+function kfm_createFileUploadPanel(contentsonly){
+       { // create form
+               var kfm_uploadPanel_checkForZip=function(e){
+                       e=new Event(e);
+                       e.stopPropagation();
+                       var v=this.value;
+                       var h=(v.indexOf('.')==-1||v.replace(/.*(\.[^.]*)/,'$1')!='.zip');
+                       $('kfm_unzip1').setStyles({
+                               'visibility':(h?'hidden':'visible')
+                       });
+                       $('kfm_unzip2').setStyles('visibility:'+(h?'hidden':'visible'));
+               }
+               var sel=newSelectbox('uploadType',[kfm.lang.Upload,kfm.lang.CopyFromURL],0,0,function(){
+                       var copy=parseInt(this.selectedIndex);
+                       var unzip1=$('kfm_unzip1'),unzip2=$('kfm_unzip2'),file=$('kfm_file'),url=$('kfm_url');
+                       if(unzip1)unzip1.setStyles({
+                               'visibility':'hidden'
+                       });
+                       if(unzip2)unzip2.setStyles({
+                               'visibility':'hidden'
+                       });
+                       if(file)file.value='';
+                       if(url)url.value='';
+                       $('kfm_uploadWrapper').setStyles({
+                               'display':(copy?'none':'block')
+                       });
+                       $('kfm_copyForm').setStyles({
+                               'display':(copy?'block':'none')
+                       });
+               });
+               { // upload from computer
+                       var wrapper=new Element('div',{
+                               'id':'kfm_uploadWrapper'
+                       });
+                       { // normal single-file upload form
+                               var f1=newForm('upload.php','POST','multipart/form-data','kfm_iframe');
+                               f1.id='kfm_uploadForm';
+                               var iframe=new Element('iframe',{
+                                       'id':'kfm_iframe',
+                                       'name':'kfm_iframe',
+                                       'src':'javascript:false',
+                                       'styles':{
+                                               'display':'none'
+                                       }
+                               });
+                               var max_upload_size=new Element('input',{
+                                       'id':'MAX_FILE_SIZE',
+                                       'name':'MAX_FILE_SIZE',
+                                       'type':'hidden',
+                                       'value':'9999999999'
+                               });
+                               var submit=newInput('upload','submit',kfm.lang.Upload);
+                               if(!window.ie)submit.addEvent('click',function(e){
+                                       e=new Event(e);
+                                       if(e.rightClick)return;
+                                       setTimeout('$("kfm_file").type="text";$("kfm_file").type="file"',1);
+                               });
+                               var input=newInput('kfm_file','file');
+                               input.addEvent('keyup',kfm_uploadPanel_checkForZip);
+                               input.addEvent('change',kfm_uploadPanel_checkForZip);
+                               var unzip1=new Element('span',{
+                                       'id':'kfm_unzip1',
+                                       'class':'kfm_unzipWhenUploaded',
+                                       'styles':{
+                                               'visibility':'hidden'
+                                       }
+                               });
+                               kfm.addEl(unzip1,[newInput('kfm_unzipWhenUploaded','checkbox'),kfm.lang.ExtractAfterUpload]);
+                               kfm.addEl(f1,[input,max_upload_size,submit,unzip1]);
+                               wrapper.appendChild(f1);
+                       }
+                       if(kfm_vars.use_multiple_file_upload){ // load multi-upload thing if possible
+                               var t=new Element('table');
+                               t.id='kfm_uploadFormSwf';
+                               $j(t).css('display','none')
+                               var r=t.insertRow(0);
+                               var c=r.insertCell(0);
+                               var b1=new Element('input',{
+                                       'type':'button',
+                                       'value':kfm.lang.Browse
+                               });
+                               c.appendChild(b1);
+                               c=r.insertCell(1);
+                               var b2=new Element('input',{
+                                       'id':'kfm_fileUploadSWFCancel',
+                                       'type':'button',
+                                       'value':kfm.lang.Cancel,
+                                       'disabled':'disabled'
+                               });
+                               c.appendChild(b2);
+                               r=t.insertRow(1);
+                               c=r.insertCell(0);
+                               c.colSpan=2;
+                               c.id='kfm_uploadProgress';
+                               $(c).setHTML('&nbsp;');
+                               wrapper.appendChild(t);
+                               window.swfUpload=new SWFUpload({
+                                       upload_url:"../../upload.php?swf=1&kfm_session="+window.session_key+"&PHPSESSID="+window.phpsession, // relative to the flash
+                                       upload_cookies:["kfm_session"],
+                                       flash_url : "j/swfupload-2.1.0b2/swfupload_f9.swf",
+                                       file_size_limit : "9999999999",
+                                       file_dialog_complete_handler:function(a){
+                                               $('kfm_fileUploadSWFCancel').disabled=null;
+                                               this.kfm_file_at=1;
+                                               this.settings.upload_progress_handler({'size':1},0);
+                                               this.startUpload();
+                                       },
+                                       upload_progress_handler:function(file,bytes_uploaded){
+                                               var percent=Math.ceil((bytes_uploaded/file.size)*100);
+                                               $('kfm_uploadProgress').setHTML('file '+window.swfUpload.kfm_file_at+' :'+percent+'%');
+                                       },
+                                       file_cancelled_handler:function(a){
+                                               $('kfm_uploadProgress').setHTML('&nbsp;');
+                                               $('kfm_fileUploadSWFCancel').disabled='disabled';
+                                       },
+                                       upload_success_handler:function(a,sdata){
+                                               ++window.swfUpload.kfm_file_at;
+                                               if(sdata!='OK')new Notice("error uploading file:\n\n"+sdata); // TODO: new string
+                                               setTimeout("window.swfUpload.startUpload()",1);
+                                       },
+                                       upload_complete_handler:function(a){
+                                               x_kfm_loadFiles(kfm_cwd_id,kfm_refreshFiles);
+                                               $('kfm_uploadProgress').setHTML('&nbsp;');
+                                               $('kfm_fileUploadSWFCancel').disabled='disabled';
+                                       },
+                                       swfupload_pre_load_handler:function(){},
+                                       swfupload_loaded_handler:function(){
+                                               $('kfm_uploadForm').remove();
+                                               $j('#kfm_uploadFormSwf').css('display','block');
+                                       },
+                                       error_handler:function(a){
+                                               alert(a);
+                                       },
+                                       minimum_flash_version : "9.0.28",
+                                       ui_container_id : "kfm_uploadFormSwf",
+                                       degraded_container_id : "kfm_uploadForm",
+                                       debug:false
+                               });
+                               b1.addEvent('click',function(e){
+                                       e=new Event(e);
+                                       if(e.rightClick)return;
+                                       window.swfUpload.selectFiles();
+                               });
+                               b2.addEvent('click',function(e){
+                                       e=new Event(e);
+                                       if(e.rightClick)return;
+                                       window.swfUpload.cancelUpload();
+                               });
+                       }
+               }
+               { // copy from URL
+                       var f2=new Element('div',{
+                               'id':'kfm_copyForm',
+                               'styles':{
+                                       'display':'none'
+                               }
+                       });
+                       var submit2=newInput('upload','submit',kfm.lang.CopyFromURL);
+                       var inp2=newInput('kfm_url',0,0,0,0,'width:100%');
+                       inp2.onkeyup=kfm_uploadPanel_checkForZip;
+                       inp2.onchange=kfm_uploadPanel_checkForZip;
+                       submit2.onclick=kfm_downloadFileFromUrl;
+                       var unzip2=new Element('span',{
+                               'id':'kfm_unzip2',
+                               'class':'kfm_unzipWhenUploaded',
+                               'styles':{
+                                       'visibility':'hidden'
+                               }
+                       });
+                       kfm.addEl(unzip2,[newInput('kfm_unzipWhenUploaded','checkbox'),kfm.lang.ExtractAfterUpload]);
+                       kfm.addEl(f2,[inp2,submit2,unzip2]);
+               }
+       }
+       var contents=[sel,wrapper,iframe,f2];
+       return contentsonly?contents:kfm_createPanel(kfm.lang.FileUpload,'kfm_file_upload_panel',contents,{maxedState:3,state:3,order:2});
+}
+function kfm_createFileDetailsPanel(){
+       return kfm_createPanel(kfm.lang.FileDetails,'kfm_file_details_panel',1,{abilities:1,order:4});
+}
+function kfm_createPanel(title,id,subels,vars){
+       // states:    0=minimised,1=maximised,2=fixed-height, 3=fixed-height-maxed
+       // abilities: -1=disabled,0=not closable,1=closable
+       var el=$extend(
+               kfm.addEl(
+                       new Element('div',{
+                               'id':id,
+                               'class':'kfm_panel'
+                       }),
+                       [
+                               (new Element('div',{
+                                       'class':'kfm_panel_header'
+                               })).setHTML(title),
+                               kfm.addEl(new Element('div',{
+                                       'class':'kfm_panel_body'
+                               }),subels)
+                       ]
+               ),
+               {
+                       state:0,height:0,panel_title:title,abilities:0,visible:1,order:99,
+                       addCloseButton:function(){if(this.abilities&1)this.addButton('removePanel','','x',kfm.lang.Close)},
+                       addMaxButton:function(){this.addButton('maximisePanel','','M',kfm.lang.Maximise)},
+                       addMinButton:function(){this.addButton('minimisePanel','','_',kfm.lang.Minimise)},
+                       addMoveDownButton:function(){if(this.id!=this.parentNode.panels[this.parentNode.panels.length-1])this.addButton('movePanel',',1','d',kfm.lang.MoveDown)},
+                       addMoveUpButton:function(){if(this.id!=this.parentNode.panels[0])this.addButton('movePanel',',-1','u',kfm.lang.MoveUp)},
+                       addRestoreButton:function(){this.addButton('restorePanel','','r',kfm.lang.Restore)},
+                       addButton:function(f,p,b,t){
+                               //if(this.abilities==-1 || !this.childNodes[0])return;
+                               //this.childNodes[0].appendChild(newLink('javascript:kfm_'+f+'("'+this.parentNode.id+'","'+this.id+'"'+p+')','['+b+']',0,'kfm_panel_header_'+b,t));
+                       }
+               }
+       );
+       if(vars)el=$extend(el,vars);
+       return el;
+}
+function kfm_createPanelWrapper(name){
+       return $extend(new Element('div',{
+               'id':name,
+               'class':'kfm_panel_wrapper'
+       }),{panels:[]});
+}
+function kfm_createSearchPanel(contentsonly){
+       var t=new Element('table',{
+               'id':'kfm_search_table'
+       }),r,inp,rows=0;
+       { // filename
+               r=t.insertRow(rows++);
+               r.insertCell(0).appendChild(newText(kfm.lang.Filename));
+               r.insertCell(1).appendChild(kfm_searchBoxFile());
+       }
+    /*
+       { // tags
+               r=t.insertRow(rows++);
+               r.insertCell(0).appendChild(newText(kfm.lang.Tags));
+               inp=newInput('kfm_search_tags');
+               inp.title=kfm.lang.CommaSeparated;
+               inp.onkeyup=kfm_runSearch;
+               r.insertCell(1).appendChild(inp);
+       }
+       */
+       return kfm_createPanel(kfm.lang.Search,'kfm_search_panel',t,{maxedState:3,state:3,order:3});
+}
+function kfm_createWidgetsPanel(){
+       var widgets=[];
+       kfm_widgets.each(function(el){
+               widgets.push(el.display());
+       });
+       el=kfm_createPanel('Widgets','kfm_widgets_panel',widgets,{'state':3});
+       return el;
+}
+function kfm_hasPanel(wrapper,panel){
+       for(var i=0;i<wrapper.panels.length;++i)if(wrapper.panels[i]==panel)return true;
+       return false;
+}
+function kfm_minimisePanel(wrapper,panel){
+       $(panel).state=0;
+       kfm_refreshPanels($(wrapper));
+}
+function kfm_maximisePanel(wrapper,panel){
+       wrapper=$(wrapper);
+       var p=$(panel);
+       p.state=p.maxedState==3?3:1;
+       kfm_refreshPanels($(wrapper));
+}
+function kfm_movePanel(wrapper,panel,offset){
+       wrapper=$(wrapper);
+       var i=0,j,k;
+       for(;i<wrapper.panels.length;++i)if(wrapper.panels[i]==panel)j=i;
+       if(offset<0)--j;
+       k=wrapper.panels[j];
+       wrapper.panels[j]=wrapper.panels[j+1];
+       wrapper.panels[j+1]=k;
+       wrapper.insertBefore($(wrapper.panels[j]),$(wrapper.panels[j+1]));
+       kfm_refreshPanels(wrapper);
+}
+function kfm_refreshPanels(wrapper){
+       wrapper=$(wrapper);
+       if(!wrapper)return false;
+       var ps=wrapper.panels,i,minheight=0;
+       var minimised=[],maximised=[],fixed_height=[],fixed_height_maxed=[];
+       for(i=0;i<ps.length;++i){
+               var el=$(ps[i]);
+               if(kfm_inArray(el.id,kfm_hidden_panels))el.visible=false;
+               if(el.id=='kfm_file_upload_panel')el.visible=kfm_directories[kfm_cwd_id].is_writable;
+               if(el.visible){
+                       el.setStyles({
+                               'display':'block'
+                       });
+                       el.minheight=el.childNodes[0].offsetHeight;
+                       minheight+=el.minheight;
+                       switch(el.state){
+                               case 0: minimised[minimised.length]=ps[i]; break;
+                               case 1: maximised[maximised.length]=ps[i]; break;
+                               case 2: fixed_height[fixed_height.length]=ps[i]; break;
+                               case 3: fixed_height_maxed[fixed_height_maxed.length]=ps[i]; break;
+                               default: kfm_log(kfm.lang.UnknownPanelState+el.state);
+                       }
+               }
+               else el.setStyles({
+                       'display':'none'
+               });
+       }
+       var height=wrapper.offsetHeight;
+       for(i=0;i<minimised.length;++i){
+               var n=minimised[i];
+               var el=$(n);
+               el.childNodes[1].setStyles({
+                       'display':'none'
+               });
+               var head=el.childNodes[0].empty(),els=[];
+               if(wrapper.panels_unlocked){
+                       el.addCloseButton();
+                       el.addMaxButton();
+                       el.addMoveDownButton();
+                       el.addMoveUpButton();
+               }
+               els[els.length]=el.panel_title;
+               kfm.addEl(head,els);
+       }
+       for(i=0;i<fixed_height.length;++i){
+               var n=fixed_height[i];
+               var el=$(n);
+               el.childNodes[1].setStyles({
+                       'height':el.height,
+                       'display':'block'
+               });
+               minheight+=el.height;
+               var head=el.childNodes[0].empty(),els=[];
+               if(wrapper.panels_unlocked){
+                       el.addCloseButton();
+                       el.addMaxButton();
+                       el.addMinButton();
+                       el.addMoveDownButton();
+                       el.addMoveUpButton();
+               }
+               els[els.length]=el.panel_title;
+               kfm.addEl(head,els);
+       }
+       for(i=0;i<fixed_height_maxed.length;++i){
+               var n=fixed_height_maxed[i];
+               var el=$(n),body=el.childNodes[1].setStyles({
+                       'height':'auto',
+                       'display':'block'
+               });
+               minheight+=body.offsetHeight;
+               var head=el.childNodes[0].empty(),els=[];
+               if(wrapper.panels_unlocked){
+                       el.addCloseButton();
+                       el.addMinButton();
+                       el.addMoveDownButton();
+                       el.addMoveUpButton();
+               }
+               els[els.length]=el.panel_title;
+               kfm.addEl(head,els);
+       }
+       if(maximised.length)var size=(height-minheight)/maximised.length;
+       for(i=0;i<maximised.length;++i){
+               var n=maximised[i];
+               var el=$(n);
+               el.childNodes[1].setStyles({
+                       'height':size,
+                       'display':'block'
+               });
+               var head=el.childNodes[0].empty(),els=[];
+               if(wrapper.panels_unlocked){
+                       el.addCloseButton();
+                       el.addRestoreButton();
+                       el.addMinButton();
+                       el.addMoveDownButton();
+                       el.addMoveUpButton();
+               }
+               els[els.length]=el.panel_title;
+               kfm.addEl(head,els);
+       }
+       { // fix order of panels
+               do{
+                       var els=wrapper.childNodes,arr=[],found=0,prev=0;
+                       for(var i=0;i<els.length,!found,els[i];++i){
+                               var order=els[i].order;
+                               if(order<prev&&i){
+                                       wrapper.insertBefore(els[i],els[i-1]);
+                                       found=1;
+                               }
+                               prev=order;
+                       }
+               }while(found);
+               for(i=0;i<els.length;++i)arr.push(els[i].order);
+       }
+}
+function kfm_removePanel(wrapper,panel){
+       var panel=$(panel);
+       if(!panel)return;
+       $(panel).visible=0;
+       kfm_refreshPanels(wrapper);
+}
+function kfm_restorePanel(wrapper,panel){
+       wrapper=$(wrapper);
+       var p=$(panel);
+       p.state=2;
+       if(!p.height)p.height=p.childNodes[1].offsetHeight;
+       kfm_refreshPanels(wrapper);
+}
+function kfm_togglePanelsUnlocked(){
+       $('kfm_left_column').panels_unlocked=1-$('kfm_left_column').panels_unlocked;
+       kfm_refreshPanels('kfm_left_column');
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/resize_handler.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/resize_handler.js
new file mode 100644 (file)
index 0000000..bd76283
--- /dev/null
@@ -0,0 +1,43 @@
+// see license.txt for licensing
+function kfm_resizeHandler(){
+       var w=window.getSize().size;
+       for(var i=0;i<kfm_resizeHandler_maxHeights.length;++i)if($(kfm_resizeHandler_maxHeights[i]))$(kfm_resizeHandler_maxHeights[i]).setStyle('height',w.y);
+       for(var i=0;i<kfm_resizeHandler_maxWidths.length;++i)if($(kfm_resizeHandler_maxWidths[i]))$(kfm_resizeHandler_maxWidths[i]).setStyle('width',w.x);
+       var el=$('kfm_codepressTableCell');
+       if(el){
+               var iframe=$E('iframe',el);
+               if(iframe){
+                       iframe.style.height=0;
+                       iframe.style.width=0;
+                       iframe.style.height=(el.offsetHeight-10)+'px';
+                       iframe.style.width=(el.offsetWidth-10)+'px';
+               }
+       }
+       kfm_refreshPanels('kfm_left_column');
+       var els=$ES('body *');
+       els.each(function(el){
+               if(el.parentResized)el.parentResized();
+       });
+}
+function kfm_resizeHandler_add(name){
+       kfm_resizeHandler_addMaxWidth(name);
+       kfm_resizeHandler_addMaxHeight(name);
+}
+function kfm_resizeHandler_addMaxHeight(name){
+       if(!kfm_resizeHandler_maxHeights.contains(name))kfm_resizeHandler_maxHeights.push(name);
+}
+function kfm_resizeHandler_addMaxWidth(name){
+       if(!kfm_resizeHandler_maxWidths.contains(name))kfm_resizeHandler_maxWidths.push(name);
+}
+function kfm_resizeHandler_remove(name){
+       kfm_resizeHandler_removeMaxWidth(name);
+       kfm_resizeHandler_removeMaxHeight(name);
+}
+function kfm_resizeHandler_removeMaxHeight(name){
+       if(!kfm_resizeHandler_maxHeights.contains(name))kfm_resizeHandler_maxHeights.remove(name);
+}
+function kfm_resizeHandler_removeMaxWidth(name){
+       if(!kfm_resizeHandler_maxWidths.contains(name))kfm_resizeHandler_maxWidths.remove(name);
+}
+var kfm_resizeHandler_maxHeights=[];
+var kfm_resizeHandler_maxWidths=[];
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/search.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/search.js
new file mode 100644 (file)
index 0000000..b60aa86
--- /dev/null
@@ -0,0 +1,20 @@
+// see license.txt for licensing
+function kfm_runSearch(){
+       kfm_run_delayed('search',kfm_runSearch2);
+}
+function kfm_runSearch2(){
+       var keywords='',tags='';
+       var kEl=$("kfm_search_keywords"),tEl=$("kfm_search_tags");
+       if(kEl)keywords=kEl.value;
+       if(tEl)tags=tEl.value;
+       if(keywords==""&&tags=="")x_kfm_loadFiles(kfm_cwd_id,kfm_refreshFiles);
+       else x_kfm_search(keywords,tags,kfm_refreshFiles)
+}
+function kfm_searchBoxFile(){
+       return new Element('input',{
+               'id':'kfm_search_keywords',
+               'events':{
+                       'keyup':kfm_runSearch
+               }
+       });
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/swfupload-2.1.0b2/swfupload.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/swfupload-2.1.0b2/swfupload.js
new file mode 100755 (executable)
index 0000000..7095cf9
--- /dev/null
@@ -0,0 +1,725 @@
+/**\r
+ * SWFUpload v2.1.0 by Jacob Roberts, Feb 2008, http://www.swfupload.org, http://swfupload.googlecode.com, http://www.swfupload.org\r
+ * -------- -------- -------- -------- -------- -------- -------- --------\r
+ * SWFUpload is (c) 2006 Lars Huring, Olov Nilzén and Mammon Media and is released under the MIT License:\r
+ * http://www.opensource.org/licenses/mit-license.php\r
+ *\r
+ * See Changelog.txt for version history\r
+ *\r
+ */\r
+\r
+\r
+/* *********** */\r
+/* Constructor */\r
+/* *********** */\r
+\r
+var SWFUpload = function (settings) {\r
+       this.initSWFUpload(settings);\r
+};\r
+\r
+SWFUpload.prototype.initSWFUpload = function (settings) {\r
+       try {\r
+               this.customSettings = {};       // A container where developers can place their own settings associated with this instance.\r
+               this.settings = settings;\r
+               this.eventQueue = [];\r
+               this.movieName = "SWFUpload_" + SWFUpload.movieCount++;\r
+               this.movieElement = null;\r
+\r
+               // Setup global control tracking\r
+               SWFUpload.instances[this.movieName] = this;\r
+\r
+               // Load the settings.  Load the Flash movie.\r
+               this.initSettings();\r
+               this.loadFlash();\r
+               this.displayDebugInfo();\r
+       } catch (ex) {\r
+               delete SWFUpload.instances[this.movieName];\r
+               throw ex;\r
+       }\r
+};\r
+\r
+/* *************** */\r
+/* Static Members  */\r
+/* *************** */\r
+SWFUpload.instances = {};\r
+SWFUpload.movieCount = 0;\r
+SWFUpload.version = "2.1.0 beta 1";\r
+SWFUpload.QUEUE_ERROR = {\r
+       QUEUE_LIMIT_EXCEEDED                    : -100,\r
+       FILE_EXCEEDS_SIZE_LIMIT                 : -110,\r
+       ZERO_BYTE_FILE                                  : -120,\r
+       INVALID_FILETYPE                                : -130\r
+};\r
+SWFUpload.UPLOAD_ERROR = {\r
+       HTTP_ERROR                                              : -200,\r
+       MISSING_UPLOAD_URL                      : -210,\r
+       IO_ERROR                                                : -220,\r
+       SECURITY_ERROR                                  : -230,\r
+       UPLOAD_LIMIT_EXCEEDED                   : -240,\r
+       UPLOAD_FAILED                                   : -250,\r
+       SPECIFIED_FILE_ID_NOT_FOUND             : -260,\r
+       FILE_VALIDATION_FAILED                  : -270,\r
+       FILE_CANCELLED                                  : -280,\r
+       UPLOAD_STOPPED                                  : -290\r
+};\r
+SWFUpload.FILE_STATUS = {\r
+       QUEUED           : -1,\r
+       IN_PROGRESS      : -2,\r
+       ERROR            : -3,\r
+       COMPLETE         : -4,\r
+       CANCELLED        : -5\r
+};\r
+\r
+\r
+/* ******************** */\r
+/* Instance Members  */\r
+/* ******************** */\r
+\r
+// Private: initSettings ensures that all the\r
+// settings are set, getting a default value if one was not assigned.\r
+SWFUpload.prototype.initSettings = function () {\r
+       this.ensureDefault = function (settingName, defaultValue) {\r
+               this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];\r
+       };\r
+       \r
+       // Upload backend settings\r
+       this.ensureDefault("upload_url", "");\r
+       this.ensureDefault("file_post_name", "Filedata");\r
+       this.ensureDefault("post_params", {});\r
+       this.ensureDefault("use_query_string", false);\r
+       this.ensureDefault("requeue_on_error", false);\r
+       \r
+       // File Settings\r
+       this.ensureDefault("file_types", "*.*");\r
+       this.ensureDefault("file_types_description", "All Files");\r
+       this.ensureDefault("file_size_limit", 0);       // Default zero means "unlimited"\r
+       this.ensureDefault("file_upload_limit", 0);\r
+       this.ensureDefault("file_queue_limit", 0);\r
+\r
+       // Flash Settings\r
+       this.ensureDefault("flash_url", "swfupload_f9.swf");\r
+       this.ensureDefault("flash_color", "#FFFFFF");\r
+\r
+       // Debug Settings\r
+       this.ensureDefault("debug", false);\r
+       this.settings.debug_enabled = this.settings.debug;      // Here to maintain v2 API\r
+       \r
+       // Event Handlers\r
+       this.settings.return_upload_start_handler = this.returnUploadStart;\r
+       this.ensureDefault("swfupload_loaded_handler", null);\r
+       this.ensureDefault("file_dialog_start_handler", null);\r
+       this.ensureDefault("file_queued_handler", null);\r
+       this.ensureDefault("file_queue_error_handler", null);\r
+       this.ensureDefault("file_dialog_complete_handler", null);\r
+       \r
+       this.ensureDefault("upload_start_handler", null);\r
+       this.ensureDefault("upload_progress_handler", null);\r
+       this.ensureDefault("upload_error_handler", null);\r
+       this.ensureDefault("upload_success_handler", null);\r
+       this.ensureDefault("upload_complete_handler", null);\r
+       \r
+       this.ensureDefault("debug_handler", this.debugMessage);\r
+\r
+       this.ensureDefault("custom_settings", {});\r
+\r
+       // Other settings\r
+       this.customSettings = this.settings.custom_settings;\r
+       \r
+       delete this.ensureDefault;\r
+};\r
+\r
+// Private: loadFlash generates the HTML tag for the Flash\r
+// It then adds the flash to the body\r
+SWFUpload.prototype.loadFlash = function () {\r
+       var targetElement, container;\r
+\r
+       // Make sure an element with the ID we are going to use doesn't already exist\r
+       if (document.getElementById(this.movieName) !== null) {\r
+               throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";\r
+       }\r
+\r
+       // Get the body tag where we will be adding the flash movie\r
+       targetElement = document.getElementsByTagName("body")[0];\r
+\r
+       if (targetElement == undefined) {\r
+               throw "Could not find the 'body' element.";\r
+       }\r
+\r
+       // Append the container and load the flash\r
+       container = document.createElement("div");\r
+       container.style.width = "1px";\r
+       container.style.height = "1px";\r
+\r
+       targetElement.appendChild(container);\r
+       container.innerHTML = this.getFlashHTML();      // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)\r
+};\r
+\r
+// Private: getFlashHTML generates the object tag needed to embed the flash in to the document\r
+SWFUpload.prototype.getFlashHTML = function () {\r
+       // Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay\r
+       return ['<object id="', this.movieName, '" type="application/x-shockwave-flash" data="', this.settings.flash_url, '" width="1" height="1" style="-moz-user-focus: ignore;">',\r
+                               '<param name="movie" value="', this.settings.flash_url, '" />',\r
+                               '<param name="bgcolor" value="', this.settings.flash_color, '" />',\r
+                               '<param name="quality" value="high" />',\r
+                               '<param name="menu" value="false" />',\r
+                               '<param name="allowScriptAccess" value="always" />',\r
+                               '<param name="flashvars" value="' + this.getFlashVars() + '" />',\r
+                               '</object>'].join("");\r
+};\r
+\r
+// Private: getFlashVars builds the parameter string that will be passed\r
+// to flash in the flashvars param.\r
+SWFUpload.prototype.getFlashVars = function () {\r
+       // Build a string from the post param object\r
+       var paramString = this.buildParamString();\r
+\r
+       // Build the parameter string\r
+       return ["movieName=", encodeURIComponent(this.movieName),\r
+                       "&amp;uploadURL=", encodeURIComponent(this.settings.upload_url),\r
+                       "&amp;useQueryString=", encodeURIComponent(this.settings.use_query_string),\r
+                       "&amp;requeueOnError=", encodeURIComponent(this.settings.requeue_on_error),\r
+                       "&amp;params=", encodeURIComponent(paramString),\r
+                       "&amp;filePostName=", encodeURIComponent(this.settings.file_post_name),\r
+                       "&amp;fileTypes=", encodeURIComponent(this.settings.file_types),\r
+                       "&amp;fileTypesDescription=", encodeURIComponent(this.settings.file_types_description),\r
+                       "&amp;fileSizeLimit=", encodeURIComponent(this.settings.file_size_limit),\r
+                       "&amp;fileUploadLimit=", encodeURIComponent(this.settings.file_upload_limit),\r
+                       "&amp;fileQueueLimit=", encodeURIComponent(this.settings.file_queue_limit),\r
+                       "&amp;debugEnabled=", encodeURIComponent(this.settings.debug_enabled)].join("");\r
+};\r
+\r
+// Public: getMovieElement retrieves the DOM reference to the Flash element added by SWFUpload\r
+// The element is cached after the first lookup\r
+SWFUpload.prototype.getMovieElement = function () {\r
+       if (this.movieElement == undefined) {\r
+               this.movieElement = document.getElementById(this.movieName);\r
+       }\r
+\r
+       if (this.movieElement === null) {\r
+               throw "Could not find Flash element";\r
+       }\r
+       \r
+       return this.movieElement;\r
+};\r
+\r
+// Private: buildParamString takes the name/value pairs in the post_params setting object\r
+// and joins them up in to a string formatted "name=value&amp;name=value"\r
+SWFUpload.prototype.buildParamString = function () {\r
+       var postParams = this.settings.post_params;\r
+       var paramStringPairs = [];\r
+\r
+       if (typeof(postParams) === "object") {\r
+               for (var name in postParams) {\r
+                       if (postParams.hasOwnProperty(name)) {\r
+                               paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString()));\r
+                       }\r
+               }\r
+       }\r
+\r
+       return paramStringPairs.join("&amp;");\r
+};\r
+\r
+// Public: displayDebugInfo prints out settings and configuration\r
+// information about this SWFUpload instance.\r
+// This function (and any references to it) can be deleted when placing\r
+// SWFUpload in production.\r
+SWFUpload.prototype.displayDebugInfo = function () {\r
+       this.debug(\r
+               [\r
+                       "---SWFUpload Instance Info---\n",\r
+                       "Version: ", SWFUpload.version, "\n",\r
+                       "Movie Name: ", this.movieName, "\n",\r
+                       "Settings:\n",\r
+                       "\t", "upload_url:             ", this.settings.upload_url, "\n",\r
+                       "\t", "use_query_string:       ", this.settings.use_query_string.toString(), "\n",\r
+                       "\t", "file_post_name:         ", this.settings.file_post_name, "\n",\r
+                       "\t", "post_params:            ", this.settings.post_params.toString(), "\n",\r
+                       "\t", "file_types:             ", this.settings.file_types, "\n",\r
+                       "\t", "file_types_description: ", this.settings.file_types_description, "\n",\r
+                       "\t", "file_size_limit:        ", this.settings.file_size_limit, "\n",\r
+                       "\t", "file_upload_limit:      ", this.settings.file_upload_limit, "\n",\r
+                       "\t", "file_queue_limit:       ", this.settings.file_queue_limit, "\n",\r
+                       "\t", "flash_url:              ", this.settings.flash_url, "\n",\r
+                       "\t", "flash_color:            ", this.settings.flash_color, "\n",\r
+                       "\t", "debug:                  ", this.settings.debug.toString(), "\n",\r
+                       "\t", "custom_settings:        ", this.settings.custom_settings.toString(), "\n",\r
+                       "Event Handlers:\n",\r
+                       "\t", "swfupload_loaded_handler assigned:  ", (typeof(this.settings.swfupload_loaded_handler) === "function").toString(), "\n",\r
+                       "\t", "file_dialog_start_handler assigned: ", (typeof(this.settings.file_dialog_start_handler) === "function").toString(), "\n",\r
+                       "\t", "file_queued_handler assigned:       ", (typeof(this.settings.file_queued_handler) === "function").toString(), "\n",\r
+                       "\t", "file_queue_error_handler assigned:  ", (typeof(this.settings.file_queue_error_handler) === "function").toString(), "\n",\r
+                       "\t", "upload_start_handler assigned:      ", (typeof(this.settings.upload_start_handler) === "function").toString(), "\n",\r
+                       "\t", "upload_progress_handler assigned:   ", (typeof(this.settings.upload_progress_handler) === "function").toString(), "\n",\r
+                       "\t", "upload_error_handler assigned:      ", (typeof(this.settings.upload_error_handler) === "function").toString(), "\n",\r
+                       "\t", "upload_success_handler assigned:    ", (typeof(this.settings.upload_success_handler) === "function").toString(), "\n",\r
+                       "\t", "upload_complete_handler assigned:   ", (typeof(this.settings.upload_complete_handler) === "function").toString(), "\n",\r
+                       "\t", "debug_handler assigned:             ", (typeof(this.settings.debug_handler) === "function").toString(), "\n"\r
+               ].join("")\r
+       );\r
+};\r
+\r
+/* Note: addSetting and getSetting are no longer used by SWFUpload but are included\r
+       the maintain v2 API compatibility\r
+*/\r
+// Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used.\r
+SWFUpload.prototype.addSetting = function (name, value, default_value) {\r
+    if (value == undefined) {\r
+        return (this.settings[name] = default_value);\r
+    } else {\r
+        return (this.settings[name] = value);\r
+       }\r
+};\r
+\r
+// Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found.\r
+SWFUpload.prototype.getSetting = function (name) {\r
+    if (this.settings[name] != undefined) {\r
+        return this.settings[name];\r
+       }\r
+\r
+    return "";\r
+};\r
+\r
+\r
+\r
+// Private: callFlash handles function calls made to the Flash element.\r
+// Calls are made with a setTimeout for some functions to work around\r
+// bugs in the ExternalInterface library.\r
+\r
+// NOTE: if we don't need to call StartUpload with a timeout anymore then we can simplify this\r
+// function and remove all the withTimeout stuff\r
+SWFUpload.prototype.callFlash = function (functionName, withTimeout, argumentArray) {\r
+       withTimeout = !!withTimeout || false;\r
+       argumentArray = argumentArray || [];\r
+       \r
+       var self = this;\r
+       var callFunction = function () {\r
+               var movieElement = self.getMovieElement();\r
+               var returnValue;\r
+               if (typeof(movieElement[functionName]) === "function") {\r
+                       // We have to go through all this if/else stuff because the Flash functions don't have apply() and only accept the exact number of arguments.\r
+                       if (argumentArray.length === 0) {\r
+                               returnValue = movieElement[functionName]();\r
+                       } else if (argumentArray.length === 1) {\r
+                               returnValue = movieElement[functionName](argumentArray[0]);\r
+                       } else if (argumentArray.length === 2) {\r
+                               returnValue = movieElement[functionName](argumentArray[0], argumentArray[1]);\r
+                       } else if (argumentArray.length === 3) {\r
+                               returnValue = movieElement[functionName](argumentArray[0], argumentArray[1], argumentArray[2]);\r
+                       } else {\r
+                               throw "Too many arguments";\r
+                       }\r
+                       \r
+                       // Unescape file post param values\r
+                       if (returnValue != undefined && typeof(returnValue.post) === "object") {\r
+                               returnValue = self.unescapeFilePostParams(returnValue);\r
+                       }\r
+                       \r
+                       return returnValue;\r
+               } else {\r
+                       throw "Invalid function name";\r
+               }\r
+       };\r
+       \r
+       if (withTimeout) {\r
+               setTimeout(callFunction, 0);\r
+       } else {\r
+               return callFunction();\r
+       }\r
+};\r
+\r
+\r
+/* *****************************\r
+       -- Flash control methods --\r
+       Your UI should use these\r
+       to operate SWFUpload\r
+   ***************************** */\r
+\r
+// Public: selectFile causes a File Selection Dialog window to appear.  This\r
+// dialog only allows 1 file to be selected.\r
+SWFUpload.prototype.selectFile = function () {\r
+       this.callFlash("SelectFile");\r
+};\r
+\r
+// Public: selectFiles causes a File Selection Dialog window to appear/ This\r
+// dialog allows the user to select any number of files\r
+// Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names.\r
+// If the selection name length is too long the dialog will fail in an unpredictable manner.  There is no work-around\r
+// for this bug.\r
+SWFUpload.prototype.selectFiles = function () {\r
+       this.callFlash("SelectFiles");\r
+};\r
+\r
+\r
+// Public: startUpload starts uploading the first file in the queue unless\r
+// the optional parameter 'fileID' specifies the ID \r
+SWFUpload.prototype.startUpload = function (fileID) {\r
+       // NOTE: Testing this without using a setTimeout. Since StartUpload was reworked to use ReturnUploadStart\r
+       // it might not be necessary anymore\r
+       this.callFlash("StartUpload", false, [fileID]);\r
+};\r
+\r
+/* Cancels a the file upload.  You must specify a file_id */\r
+// Public: cancelUpload cancels any queued file.  The fileID parameter\r
+// must be specified.\r
+SWFUpload.prototype.cancelUpload = function (fileID) {\r
+       this.callFlash("CancelUpload", false, [fileID]);\r
+};\r
+\r
+// Public: stopUpload stops the current upload and requeues the file at the beginning of the queue.\r
+// If nothing is currently uploading then nothing happens.\r
+SWFUpload.prototype.stopUpload = function () {\r
+       this.callFlash("StopUpload");\r
+};\r
+\r
+/* ************************\r
+ * Settings methods\r
+ *   These methods change the SWFUpload settings.\r
+ *   SWFUpload settings should not be changed directly on the settings object\r
+ *   since many of the settings need to be passed to Flash in order to take\r
+ *   effect.\r
+ * *********************** */\r
+\r
+// Public: getStats gets the file statistics object.  It looks like this (where n is a number):\r
+SWFUpload.prototype.getStats = function () {\r
+       return this.callFlash("GetStats");\r
+};\r
+\r
+// Public: setStats changes the SWFUpload statistics.  You shouldn't need to \r
+// change the statistics but you can.  Changing the statistics does not\r
+// affect SWFUpload accept for the successful_uploads count which is used\r
+// by the upload_limit setting to determine how many files the user may upload.\r
+SWFUpload.prototype.setStats = function (statsObject) {\r
+       this.callFlash("SetStats", false, [statsObject]);\r
+};\r
+\r
+// Public: setCredentials that will be used to authenticate to the upload_url.\r
+// Note: This feature does not work.  It has been added in anticipation of\r
+// the Flex 3 SDK which has not been released yet.\r
+SWFUpload.prototype.setCredentials = function (name, password) {\r
+       this.callFlash("SetCrednetials", false, [name, password]);\r
+};\r
+\r
+// Public: getFile retrieves a File object by ID or Index.  If the file is\r
+// not found then 'null' is returned.\r
+SWFUpload.prototype.getFile = function (fileID) {\r
+       if (typeof(fileID) === "number") {\r
+               return this.callFlash("GetFileByIndex", false, [fileID]);\r
+       } else {\r
+               return this.callFlash("GetFile", false, [fileID]);\r
+       }\r
+};\r
+\r
+// Public: addFileParam sets a name/value pair that will be posted with the\r
+// file specified by the Files ID.  If the name already exists then the\r
+// exiting value will be overwritten.\r
+SWFUpload.prototype.addFileParam = function (fileID, name, value) {\r
+       return this.callFlash("AddFileParam", false, [fileID, name, value]);\r
+};\r
+\r
+// Public: removeFileParam removes a previously set (by addFileParam) name/value\r
+// pair from the specified file.\r
+SWFUpload.prototype.removeFileParam = function (fileID, name) {\r
+       this.callFlash("RemoveFileParam", false, [fileID, name]);\r
+};\r
+\r
+// Public: setUploadUrl changes the upload_url setting.\r
+SWFUpload.prototype.setUploadURL = function (url) {\r
+       this.settings.upload_url = url.toString();\r
+       this.callFlash("SetUploadURL", false, [url]);\r
+};\r
+\r
+// Public: setPostParams changes the post_params setting\r
+SWFUpload.prototype.setPostParams = function (paramsObject) {\r
+       this.settings.post_params = paramsObject;\r
+       this.callFlash("SetPostParams", false, [paramsObject]);\r
+};\r
+\r
+// Public: addPostParam adds post name/value pair.  Each name can have only one value.\r
+SWFUpload.prototype.addPostParam = function (name, value) {\r
+       this.settings.post_params[name] = value;\r
+       this.callFlash("SetPostParams", false, [this.settings.post_params]);\r
+};\r
+\r
+// Public: removePostParam deletes post name/value pair.\r
+SWFUpload.prototype.removePostParam = function (name) {\r
+       delete this.settings.post_params[name];\r
+       this.callFlash("SetPostParams", false, [this.settings.post_params]);\r
+};\r
+\r
+// Public: setFileTypes changes the file_types setting and the file_types_description setting\r
+SWFUpload.prototype.setFileTypes = function (types, description) {\r
+       this.settings.file_types = types;\r
+       this.settings.file_types_description = description;\r
+       this.callFlash("SetFileTypes", false, [types, description]);\r
+};\r
+\r
+// Public: setFileSizeLimit changes the file_size_limit setting\r
+SWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) {\r
+       this.settings.file_size_limit = fileSizeLimit;\r
+       this.callFlash("SetFileSizeLimit", false, [fileSizeLimit]);\r
+};\r
+\r
+// Public: setFileUploadLimit changes the file_upload_limit setting\r
+SWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) {\r
+       this.settings.file_upload_limit = fileUploadLimit;\r
+       this.callFlash("SetFileUploadLimit", false, [fileUploadLimit]);\r
+};\r
+\r
+// Public: setFileQueueLimit changes the file_queue_limit setting\r
+SWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) {\r
+       this.settings.file_queue_limit = fileQueueLimit;\r
+       this.callFlash("SetFileQueueLimit", false, [fileQueueLimit]);\r
+};\r
+\r
+// Public: setFilePostName changes the file_post_name setting\r
+SWFUpload.prototype.setFilePostName = function (filePostName) {\r
+       this.settings.file_post_name = filePostName;\r
+       this.callFlash("SetFilePostName", false, [filePostName]);\r
+};\r
+\r
+// Public: setUseQueryString changes the use_query_string setting\r
+SWFUpload.prototype.setUseQueryString = function (useQueryString) {\r
+       this.settings.use_query_string = useQueryString;\r
+       this.callFlash("SetUseQueryString", false, [useQueryString]);\r
+};\r
+\r
+// Public: setRequeueOnError changes the requeue_on_error setting\r
+SWFUpload.prototype.setRequeueOnError = function (requeueOnError) {\r
+       this.settings.requeue_on_error = requeueOnError;\r
+       this.callFlash("SetRequeueOnError", false, [requeueOnError]);\r
+};\r
+\r
+// Public: setDebugEnabled changes the debug_enabled setting\r
+SWFUpload.prototype.setDebugEnabled = function (debugEnabled) {\r
+       this.settings.debug_enabled = debugEnabled;\r
+       this.callFlash("SetDebugEnabled", false, [debugEnabled]);\r
+};\r
+\r
+\r
+/* *******************************\r
+       Flash Event Interfaces\r
+       These functions are used by Flash to trigger the various\r
+       events.\r
+       \r
+       All these functions a Private.\r
+       \r
+       Because the ExternalInterface library is buggy the event calls\r
+       are added to a queue and the queue then executed by a setTimeout.\r
+       This ensures that events are executed in a determinate order and that\r
+       the ExternalInterface bugs are avoided.\r
+******************************* */\r
+\r
+SWFUpload.prototype.queueEvent = function (handlerName, argumentArray) {\r
+       // Warning: Don't call this.debug inside here or you'll create an infinite loop\r
+       \r
+       if (argumentArray == undefined) {\r
+               argumentArray = [];\r
+       } else if (!(argumentArray instanceof Array)) {\r
+               argumentArray = [argumentArray];\r
+       }\r
+       \r
+       var self = this;\r
+       if (typeof(this.settings[handlerName]) === "function") {\r
+               // Queue the event\r
+               this.eventQueue.push(function () {\r
+                       this.settings[handlerName].apply(this, argumentArray);\r
+               });\r
+               \r
+               // Execute the next queued event\r
+               setTimeout(function () {\r
+                       self.executeNextEvent();\r
+               }, 0);\r
+               \r
+       } else if (this.settings[handlerName] !== null) {\r
+               throw "Event handler " + handlerName + " is unknown or is not a function";\r
+       }\r
+};\r
+\r
+SWFUpload.prototype.executeNextEvent = function () {\r
+       // Warning: Don't call this.debug inside here or you'll create an infinite loop\r
+\r
+       var  f = this.eventQueue.shift();\r
+       f.apply(this);\r
+       \r
+};\r
+\r
+// Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterfance cannot have\r
+// properties that contain characters that are not valid for JavaScript identifiers. To work around this\r
+// the Flash Component escapes the parameter names and we must unescape again before passing them along.\r
+SWFUpload.prototype.unescapeFilePostParams = function (file) {\r
+       var reg = /[$]([0-9a-f]{4})/i;\r
+       var unescapedPost = {};\r
+       var uk;\r
+\r
+       for (var k in file.post) {\r
+               if (file.post.hasOwnProperty(k)) {\r
+                       uk = k;\r
+                       var match;\r
+                       while ((match = reg.exec(uk)) !== null) {\r
+                               uk = uk.replace(match[0], String.fromCharCode(parseInt("0x"+match[1], 16)));\r
+                       }\r
+                       unescapedPost[uk] = file.post[k];\r
+               }\r
+       }\r
+\r
+       file.post = unescapedPost;\r
+       return file;\r
+};\r
+\r
+SWFUpload.prototype.flashReady = function () {\r
+       // Check that the movie element is loaded correctly with its ExternalInterface methods defined\r
+       var movieElement = this.getMovieElement();\r
+       if (typeof(movieElement.StartUpload) !== "function") {\r
+               throw "ExternalInterface methods failed to initialize.";\r
+       }\r
+       \r
+       this.queueEvent("swfupload_loaded_handler");\r
+};\r
+\r
+\r
+/* This is a chance to do something before the browse window opens */\r
+SWFUpload.prototype.fileDialogStart = function () {\r
+       this.queueEvent("file_dialog_start_handler");\r
+};\r
+\r
+\r
+/* Called when a file is successfully added to the queue. */\r
+SWFUpload.prototype.fileQueued = function (file) {\r
+       file = this.unescapeFilePostParams(file);\r
+       this.queueEvent("file_queued_handler", file);\r
+};\r
+\r
+\r
+/* Handle errors that occur when an attempt to queue a file fails. */\r
+SWFUpload.prototype.fileQueueError = function (file, errorCode, message) {\r
+       file = this.unescapeFilePostParams(file);\r
+       this.queueEvent("file_queue_error_handler", [file, errorCode, message]);\r
+};\r
+\r
+/* Called after the file dialog has closed and the selected files have been queued.\r
+       You could call startUpload here if you want the queued files to begin uploading immediately. */\r
+SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued) {\r
+       this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued]);\r
+};\r
+\r
+SWFUpload.prototype.uploadStart = function (file) {\r
+       file = this.unescapeFilePostParams(file);\r
+       this.queueEvent("return_upload_start_handler", file);\r
+};\r
+\r
+SWFUpload.prototype.returnUploadStart = function (file) {\r
+       var returnValue;\r
+       if (typeof(this.settings.upload_start_handler) === "function") {\r
+               file = this.unescapeFilePostParams(file);\r
+               returnValue = this.settings.upload_start_handler.call(this, file);\r
+       } else if (this.settings.upload_start_handler != undefined) {\r
+               throw "upload_start_handler must be a function";\r
+       }\r
+\r
+       // Convert undefined to true so if nothing is returned from the upload_start_handler it is\r
+       // interpretted as 'true'.\r
+       if (returnValue === undefined) {\r
+               returnValue = true;\r
+       }\r
+       \r
+       returnValue = !!returnValue;\r
+       \r
+       this.callFlash("ReturnUploadStart", false, [returnValue]);\r
+};\r
+\r
+\r
+\r
+SWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) {\r
+       file = this.unescapeFilePostParams(file);\r
+       this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]);\r
+};\r
+\r
+SWFUpload.prototype.uploadError = function (file, errorCode, message) {\r
+       file = this.unescapeFilePostParams(file);\r
+       this.queueEvent("upload_error_handler", [file, errorCode, message]);\r
+};\r
+\r
+SWFUpload.prototype.uploadSuccess = function (file, serverData) {\r
+       file = this.unescapeFilePostParams(file);\r
+       this.queueEvent("upload_success_handler", [file, serverData]);\r
+};\r
+\r
+SWFUpload.prototype.uploadComplete = function (file) {\r
+       file = this.unescapeFilePostParams(file);\r
+       this.queueEvent("upload_complete_handler", file);\r
+};\r
+\r
+/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the\r
+   internal debug console.  You can override this event and have messages written where you want. */\r
+SWFUpload.prototype.debug = function (message) {\r
+       this.queueEvent("debug_handler", message);\r
+};\r
+\r
+\r
+/* **********************************\r
+       Debug Console\r
+       The debug console is a self contained, in page location\r
+       for debug message to be sent.  The Debug Console adds\r
+       itself to the body if necessary.\r
+\r
+       The console is automatically scrolled as messages appear.\r
+       \r
+       If you are using your own debug handler or when you deploy to production and\r
+       have debug disabled you can remove these functions to reduce the file size\r
+       and complexity.\r
+********************************** */\r
+   \r
+// Private: debugMessage is the default debug_handler.  If you want to print debug messages\r
+// call the debug() function.  When overriding the function your own function should\r
+// check to see if the debug setting is true before outputting debug information.\r
+SWFUpload.prototype.debugMessage = function (message) {\r
+       if (this.settings.debug) {\r
+               var exceptionMessage, exceptionValues = [];\r
+\r
+               // Check for an exception object and print it nicely\r
+               if (typeof(message) === "object" && typeof(message.name) === "string" && typeof(message.message) === "string") {\r
+                       for (var key in message) {\r
+                               if (message.hasOwnProperty(key)) {\r
+                                       exceptionValues.push(key + ": " + message[key]);\r
+                               }\r
+                       }\r
+                       exceptionMessage = exceptionValues.join("\n") || "";\r
+                       exceptionValues = exceptionMessage.split("\n");\r
+                       exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: ");\r
+                       SWFUpload.Console.writeLine(exceptionMessage);\r
+               } else {\r
+                       SWFUpload.Console.writeLine(message);\r
+               }\r
+       }\r
+};\r
+\r
+SWFUpload.Console = {};\r
+SWFUpload.Console.writeLine = function (message) {\r
+       var console, documentForm;\r
+\r
+       try {\r
+               console = document.getElementById("SWFUpload_Console");\r
+\r
+               if (!console) {\r
+                       documentForm = document.createElement("form");\r
+                       document.getElementsByTagName("body")[0].appendChild(documentForm);\r
+\r
+                       console = document.createElement("textarea");\r
+                       console.id = "SWFUpload_Console";\r
+                       console.style.fontFamily = "monospace";\r
+                       console.setAttribute("wrap", "off");\r
+                       console.wrap = "off";\r
+                       console.style.overflow = "auto";\r
+                       console.style.width = "700px";\r
+                       console.style.height = "350px";\r
+                       console.style.margin = "5px";\r
+                       documentForm.appendChild(console);\r
+               }\r
+\r
+               console.value += message + "\n";\r
+\r
+               console.scrollTop = console.scrollHeight - console.clientHeight;\r
+       } catch (ex) {\r
+               alert("Exception: " + ex.name + " Message: " + ex.message);\r
+       }\r
+};\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/swfupload-2.1.0b2/swfupload.swfobject.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/swfupload-2.1.0b2/swfupload.swfobject.js
new file mode 100755 (executable)
index 0000000..9fcb5f2
--- /dev/null
@@ -0,0 +1,108 @@
+/*\r
+       SWFUpload.SWFObject Plugin\r
+\r
+       Summary:\r
+               This plugin uses SWFObject to embed SWFUpload dynamically in the page.  SWFObject provides accurate Flash Player detection and DOM Ready loading.\r
+               This plugin replaces the Graceful Degradation plugin.\r
+\r
+       Features:\r
+               * swfupload_load_failed_hander event\r
+               * swfupload_pre_load_handler event\r
+               * minimum_flash_version setting (default: "9.0.28")\r
+               * SWFUpload.onload event for early loading\r
+\r
+       Usage:\r
+               Provide handlers and settings as needed.  When using the SWFUpload.SWFObject plugin you should initialize SWFUploading\r
+               in SWFUpload.onload rather than in window.onload.  When initialized this way SWFUpload can load earlier preventing the UI flicker\r
+               that was seen using the Graceful Degradation plugin.\r
+\r
+               <script type="text/javascript">\r
+                       var swfu;\r
+                       SWFUpload.onload = function () {\r
+                               swfu = new SWFUpload({\r
+                                       minimum_flash_version: "9.0.28",\r
+                                       swfupload_pre_load_handler: swfuploadPreLoad,\r
+                                       swfupload_load_failed_handler: swfuploadLoadFailed\r
+                               });\r
+                       };\r
+               </script>\r
+               \r
+       Notes:\r
+               You must provide set minimum_flash_version setting to "8" if you are using SWFUpload for Flash Player 8.\r
+               The swfuploadLoadFailed event is only fired if the minimum version of Flash Player is not met.  Other issues such as missing SWF files, browser bugs\r
+                or corrupt Flash Player installations will not trigger this event.\r
+               The swfuploadPreLoad event is fired as soon as the minimum version of Flash Player is found.  It does not wait for SWFUpload to load and can\r
+                be used to prepare the SWFUploadUI and hide alternate content.\r
+               swfobject's onDomReady event is cross-browser safe but will default to the window.onload event when DOMReady is not supported by the browser.\r
+                Early DOM Loading is supported in major modern browsers but cannot be guaranteed for every browser ever made.\r
+*/\r
+\r
+\r
+/*     SWFObject v2.0 rc4 <http://code.google.com/p/swfobject/>\r
+       Copyright (c) 2007 Geoff Stearns, Michael Williams, and Bobby van der Sluis\r
+       This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>\r
+*/\r
+var swfobject=function(){var X="undefined",P="object",a="visibility:visible",e="visibility:hidden",B="Shockwave Flash",h="ShockwaveFlash.ShockwaveFlash",V="application/x-shockwave-flash",K="SWFObjectExprInst",G=window,g=document,N=navigator,f=[],H=[],Q=null,L=null,S=false,C=false;var Y=function(){var l=typeof g.getElementById!=X&&typeof g.getElementsByTagName!=X&&typeof g.createElement!=X&&typeof g.appendChild!=X&&typeof g.replaceChild!=X&&typeof g.removeChild!=X&&typeof g.cloneNode!=X,t=[0,0,0],n=null;if(typeof N.plugins!=X&&typeof N.plugins[B]==P){n=N.plugins[B].description;if(n){n=n.replace(/^.*\s+(\S+\s+\S+$)/,"$1");t[0]=parseInt(n.replace(/^(.*)\..*$/,"$1"),10);t[1]=parseInt(n.replace(/^.*\.(.*)\s.*$/,"$1"),10);t[2]=/r/.test(n)?parseInt(n.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof G.ActiveXObject!=X){var o=null,s=false;try{o=new ActiveXObject(h+".7")}catch(k){try{o=new ActiveXObject(h+".6");t=[6,0,21];o.AllowScriptAccess="always"}catch(k){if(t[0]==6){s=true}}if(!s){try{o=new ActiveXObject(h)}catch(k){}}}if(!s&&o){try{n=o.GetVariable("$version");if(n){n=n.split(" ")[1].split(",");t=[parseInt(n[0],10),parseInt(n[1],10),parseInt(n[2],10)]}}catch(k){}}}}var v=N.userAgent.toLowerCase(),j=N.platform.toLowerCase(),r=/webkit/.test(v)?parseFloat(v.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,i=false,q=j?/win/.test(j):/win/.test(v),m=j?/mac/.test(j):/mac/.test(v);/*@cc_on i=true;@if(@_win32)q=true;@elif(@_mac)m=true;@end@*/return{w3cdom:l,pv:t,webkit:r,ie:i,win:q,mac:m}}();var d=function(){if(!Y.w3cdom){return }J(I);if(Y.ie&&Y.win){try{g.write("<script id=__ie_ondomload defer=true src=//:><\/script>");var i=b("__ie_ondomload");if(i){i.onreadystatechange=function(){if(this.readyState=="complete"){this.parentNode.removeChild(this);U()}}}}catch(j){}}if(Y.webkit&&typeof g.readyState!=X){Q=setInterval(function(){if(/loaded|complete/.test(g.readyState)){U()}},10)}if(typeof g.addEventListener!=X){g.addEventListener("DOMContentLoaded",U,null)}M(U)}();function U(){if(S){return }if(Y.ie&&Y.win){var m=W("span");try{var l=g.getElementsByTagName("body")[0].appendChild(m);l.parentNode.removeChild(l)}catch(n){return }}S=true;if(Q){clearInterval(Q);Q=null}var j=f.length;for(var k=0;k<j;k++){f[k]()}}function J(i){if(S){i()}else{f[f.length]=i}}function M(j){if(typeof G.addEventListener!=X){G.addEventListener("load",j,false)}else{if(typeof g.addEventListener!=X){g.addEventListener("load",j,false)}else{if(typeof G.attachEvent!=X){G.attachEvent("onload",j)}else{if(typeof G.onload=="function"){var i=G.onload;G.onload=function(){i();j()}}else{G.onload=j}}}}}function I(){var l=H.length;for(var j=0;j<l;j++){var m=H[j].id;if(Y.pv[0]>0){var k=b(m);if(k){H[j].width=k.getAttribute("width")?k.getAttribute("width"):"0";H[j].height=k.getAttribute("height")?k.getAttribute("height"):"0";if(O(H[j].swfVersion)){if(Y.webkit&&Y.webkit<312){T(k)}}else{if(H[j].expressInstall&&!C&&O("6.0.65")&&(Y.win||Y.mac)){D(H[j])}else{c(k)}}}}A("#"+m,a)}}function T(m){var k=m.getElementsByTagName(P)[0];if(k){var p=W("embed"),r=k.attributes;if(r){var o=r.length;for(var n=0;n<o;n++){if(r[n].nodeName.toLowerCase()=="data"){p.setAttribute("src",r[n].nodeValue)}else{p.setAttribute(r[n].nodeName,r[n].nodeValue)}}}var q=k.childNodes;if(q){var s=q.length;for(var l=0;l<s;l++){if(q[l].nodeType==1&&q[l].nodeName.toLowerCase()=="param"){p.setAttribute(q[l].getAttribute("name"),q[l].getAttribute("value"))}}}m.parentNode.replaceChild(p,m)}}function F(i){if(Y.ie&&Y.win&&O("8.0.0")){G.attachEvent("onunload",function(){var k=b(i);for(var j in k){if(typeof k[j]=="function"){k[j]=function(){}}}k.parentNode.removeChild(k)})}}function D(j){C=true;var o=b(j.id);if(o){if(j.altContentId){var l=b(j.altContentId);if(l){L=l}}else{L=Z(o)}if(!(/%$/.test(j.width))&&parseInt(j.width,10)<310){j.width="310"}if(!(/%$/.test(j.height))&&parseInt(j.height,10)<137){j.height="137"}g.title=g.title.slice(0,47)+" - Flash Player Installation";var n=Y.ie&&Y.win?"ActiveX":"PlugIn",k=g.title,m="MMredirectURL="+G.location+"&MMplayerType="+n+"&MMdoctitle="+k,p=j.id;if(Y.ie&&Y.win&&o.readyState!=4){var i=W("div");p+="SWFObjectNew";i.setAttribute("id",p);o.parentNode.insertBefore(i,o);o.style.display="none";G.attachEvent("onload",function(){o.parentNode.removeChild(o)})}R({data:j.expressInstall,id:K,width:j.width,height:j.height},{flashvars:m},p)}}function c(j){if(Y.ie&&Y.win&&j.readyState!=4){var i=W("div");j.parentNode.insertBefore(i,j);i.parentNode.replaceChild(Z(j),i);j.style.display="none";G.attachEvent("onload",function(){j.parentNode.removeChild(j)})}else{j.parentNode.replaceChild(Z(j),j)}}function Z(n){var m=W("div");if(Y.win&&Y.ie){m.innerHTML=n.innerHTML}else{var k=n.getElementsByTagName(P)[0];if(k){var o=k.childNodes;if(o){var j=o.length;for(var l=0;l<j;l++){if(!(o[l].nodeType==1&&o[l].nodeName.toLowerCase()=="param")&&!(o[l].nodeType==8)){m.appendChild(o[l].cloneNode(true))}}}}}return m}function R(AE,AC,q){var p,t=b(q);if(typeof AE.id==X){AE.id=q}if(Y.ie&&Y.win){var AD="";for(var z in AE){if(AE[z]!=Object.prototype[z]){if(z=="data"){AC.movie=AE[z]}else{if(z.toLowerCase()=="styleclass"){AD+=' class="'+AE[z]+'"'}else{if(z!="classid"){AD+=" "+z+'="'+AE[z]+'"'}}}}}var AB="";for(var y in AC){if(AC[y]!=Object.prototype[y]){AB+='<param name="'+y+'" value="'+AC[y]+'" />'}}t.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+AD+">"+AB+"</object>";F(AE.id);p=b(AE.id)}else{if(Y.webkit&&Y.webkit<312){var AA=W("embed");AA.setAttribute("type",V);for(var x in AE){if(AE[x]!=Object.prototype[x]){if(x=="data"){AA.setAttribute("src",AE[x])}else{if(x.toLowerCase()=="styleclass"){AA.setAttribute("class",AE[x])}else{if(x!="classid"){AA.setAttribute(x,AE[x])}}}}}for(var w in AC){if(AC[w]!=Object.prototype[w]){if(w!="movie"){AA.setAttribute(w,AC[w])}}}t.parentNode.replaceChild(AA,t);p=AA}else{var s=W(P);s.setAttribute("type",V);for(var v in AE){if(AE[v]!=Object.prototype[v]){if(v.toLowerCase()=="styleclass"){s.setAttribute("class",AE[v])}else{if(v!="classid"){s.setAttribute(v,AE[v])}}}}for(var u in AC){if(AC[u]!=Object.prototype[u]&&u!="movie"){E(s,u,AC[u])}}t.parentNode.replaceChild(s,t);p=s}}return p}function E(k,i,j){var l=W("param");l.setAttribute("name",i);l.setAttribute("value",j);k.appendChild(l)}function b(i){return g.getElementById(i)}function W(i){return g.createElement(i)}function O(k){var j=Y.pv,i=k.split(".");i[0]=parseInt(i[0],10);i[1]=parseInt(i[1],10);i[2]=parseInt(i[2],10);return(j[0]>i[0]||(j[0]==i[0]&&j[1]>i[1])||(j[0]==i[0]&&j[1]==i[1]&&j[2]>=i[2]))?true:false}function A(m,j){if(Y.ie&&Y.mac){return }var l=g.getElementsByTagName("head")[0],k=W("style");k.setAttribute("type","text/css");k.setAttribute("media","screen");if(!(Y.ie&&Y.win)&&typeof g.createTextNode!=X){k.appendChild(g.createTextNode(m+" {"+j+"}"))}l.appendChild(k);if(Y.ie&&Y.win&&typeof g.styleSheets!=X&&g.styleSheets.length>0){var i=g.styleSheets[g.styleSheets.length-1];if(typeof i.addRule==P){i.addRule(m,j)}}}return{registerObject:function(l,i,k){if(!Y.w3cdom||!l||!i){return }var j={};j.id=l;j.swfVersion=i;j.expressInstall=k?k:false;H[H.length]=j;A("#"+l,e)},getObjectById:function(l){var i=null;if(Y.w3cdom&&S){var j=b(l);if(j){var k=j.getElementsByTagName(P)[0];if(!k||(k&&typeof j.SetVariable!=X)){i=j}else{if(typeof k.SetVariable!=X){i=k}}}}return i},embedSWF:function(n,u,r,t,j,m,k,p,s){if(!Y.w3cdom||!n||!u||!r||!t||!j){return }r+="";t+="";if(O(j)){A("#"+u,e);var q=(typeof s==P)?s:{};q.data=n;q.width=r;q.height=t;var o=(typeof p==P)?p:{};if(typeof k==P){for(var l in k){if(k[l]!=Object.prototype[l]){if(typeof o.flashvars!=X){o.flashvars+="&"+l+"="+k[l]}else{o.flashvars=l+"="+k[l]}}}}J(function(){R(q,o,u);A("#"+u,a)})}else{if(m&&!C&&O("6.0.65")&&(Y.win||Y.mac)){A("#"+u,e);J(function(){var i={};i.id=i.altContentId=u;i.width=r;i.height=t;i.expressInstall=m;D(i);A("#"+u,a)})}}},getFlashPlayerVersion:function(){return{major:Y.pv[0],minor:Y.pv[1],release:Y.pv[2]}},hasFlashPlayerVersion:O,createSWF:function(k,j,i){if(Y.w3cdom&&S){return R(k,j,i)}else{return undefined}},createCSS:function(j,i){if(Y.w3cdom){A(j,i)}},addDomLoadEvent:J,addLoadEvent:M,getQueryParamValue:function(m){var l=g.location.search||g.location.hash;if(m==null){return l}if(l){var k=l.substring(1).split("&");for(var j=0;j<k.length;j++){if(k[j].substring(0,k[j].indexOf("="))==m){return k[j].substring((k[j].indexOf("=")+1))}}}return""},expressInstallCallback:function(){if(C&&L){var i=b(K);if(i){i.parentNode.replaceChild(L,i);L=null;C=false}}}}}();\r
+\r
+       \r
+var SWFUpload;\r
+if (typeof(SWFUpload) === "function") {\r
+       SWFUpload.onload = function () {};\r
+       \r
+       swfobject.addDomLoadEvent(function () {\r
+               if (typeof(SWFUpload.onload) === "function") {\r
+                       SWFUpload.onload.call(window);\r
+               }\r
+       });\r
+       \r
+       SWFUpload.prototype.initSettings = (function (oldInitSettings) {\r
+               return function () {\r
+                       if (typeof(oldInitSettings) === "function") {\r
+                               oldInitSettings.call(this);\r
+                       }\r
+\r
+                       this.ensureDefault = function (settingName, defaultValue) {\r
+                               this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];\r
+                       };\r
+\r
+                       this.ensureDefault("minimum_flash_version", "9.0.28");\r
+                       this.ensureDefault("swfupload_load_failed_handler", null);\r
+\r
+                       delete this.ensureDefault;\r
+\r
+               };\r
+       })(SWFUpload.prototype.initSettings);\r
+\r
+\r
+       SWFUpload.prototype.loadFlash = function (oldLoadFlash) {\r
+               return function () {\r
+                       var hasFlash = swfobject.hasFlashPlayerVersion(this.settings.minimum_flash_version);\r
+                       \r
+                       if (hasFlash) {\r
+                               this.queueEvent("swfupload_pre_load_handler");\r
+                               if (typeof(oldLoadFlash) === "function") {\r
+                                       oldLoadFlash.call(this);\r
+                               }\r
+                       } else {\r
+                               this.queueEvent("swfupload_load_failed_handler");\r
+                       }\r
+               };\r
+               \r
+       }(SWFUpload.prototype.loadFlash);\r
+                       \r
+       SWFUpload.prototype.displayDebugInfo = function (oldDisplayDebugInfo) {\r
+               return function () {\r
+                       if (typeof(oldDisplayDebugInfo) === "function") {\r
+                               oldDisplayDebugInfo.call(this);\r
+                       }\r
+                       \r
+                       this.debug(\r
+                               [\r
+                                       "SWFUpload.SWFObject Plugin settings:", "\n",\r
+                                       "\t", "minimum_flash_version:                      ", this.settings.minimum_flash_version, "\n",\r
+                                       "\t", "swfupload_load_failed_handler assigned:     ", (typeof(this.settings.swfupload_load_failed_handler) === "function").toString(), "\n",\r
+                               ].join("")\r
+                       );\r
+               };      \r
+       }(SWFUpload.prototype.displayDebugInfo);\r
+}\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/swfupload-2.1.0b2/swfupload_f8.swf b/ipf/admin/media/tiny_mce/plugins/kfm/j/swfupload-2.1.0b2/swfupload_f8.swf
new file mode 100755 (executable)
index 0000000..836151a
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/j/swfupload-2.1.0b2/swfupload_f8.swf differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/swfupload-2.1.0b2/swfupload_f9.swf b/ipf/admin/media/tiny_mce/plugins/kfm/j/swfupload-2.1.0b2/swfupload_f9.swf
new file mode 100755 (executable)
index 0000000..dd0a954
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/j/swfupload-2.1.0b2/swfupload_f9.swf differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/tags.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/tags.js
new file mode 100644 (file)
index 0000000..b966880
--- /dev/null
@@ -0,0 +1,35 @@
+// see license.txt for licensing
+function kfm_tagAdd(id){
+       kfm_prompt(kfm.lang.WhatIsTheNewTag,'',function(newTag){
+               if(newTag){
+                       files=selectedFiles.length?selectedFiles:id;
+                       x_kfm_tagAdd(files,newTag,kfm_showFileDetails);
+               }
+       });
+}
+function kfm_tagDraw(id){
+       if($type(id)!='array'){
+               if(kfm_tags[id])return (new Element('span')).setHTML(kfm_tags[id]);
+               x_kfm_getTagName(id,kfm_tagDraw);
+               return (new Element('span',{
+                       'class':'kfm_unknown_tag'
+               })).setHTML(id);
+       }
+       var name=id[1],id=id[0],els=$ES('span.kfm_unknown_tag');
+       kfm_tags[id]=name;
+       for(var i=0;i<els.length;++i){
+               var el=els[i];
+               if(el.innerHTML==id){
+                       el.innerHTML=name;
+                       el.removeClass('kfm_unknown_tag');
+               }
+       }
+}
+function kfm_tagRemove(id){
+       kfm_prompt(kfm.lang.WhichTagsDoYouWantToRemove,'',function(tagsToRemove){
+               if(tagsToRemove){
+                       files=selectedFiles.length?selectedFiles:id;
+                       x_kfm_tagRemove(files,tagsToRemove,kfm_showFileDetails);
+               }
+       });
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/j/variables.js b/ipf/admin/media/tiny_mce/plugins/kfm/j/variables.js
new file mode 100644 (file)
index 0000000..1fb03e9
--- /dev/null
@@ -0,0 +1,5 @@
+// see license.txt for licensing
+       if(!window.kfm_callerType)window.kfm_callerType='standalone';
+       var loadedScripts=[],function_urls=[],kfm_cwd_name='',kfm_cwd_id=0,kfm_cwd_subdirs=[],contextmenu=null,selectedFiles=[];
+       var kfm_tags=[],kfm_lastClicked,kfm_unique_classes=[],kfm_directory_over=0,kfm_kaejax_timeouts=[];
+       var kfm_directories=[0,{name:kfm_vars.root_folder_name,pathname:'/'}],kfm_kaejax_is_loaded=0;
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/bg.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/bg.js
new file mode 100644 (file)
index 0000000..f803de3
--- /dev/null
@@ -0,0 +1,293 @@
+/*\r
+ * See ../license.txt for licensing\r
+ *\r
+ * For further information visit:\r
+ *     http://kfm.verens.com/\r
+ *\r
+ * File Name: bg.js\r
+ *     Bulgarian language file.\r
+ *\r
+ * File Authors:\r
+ *     tondy@tondy.com\r
+ */\r
+\r
+kfm.lang=\r
+{\r
+Dir:\r
+       "ltr", // language direction\r
+ErrorPrefix:\r
+       "грешка: ",\r
+// what you see on the main page\r
+Directories:\r
+       "Папки",\r
+CurrentWorkingDir:\r
+       "Текуща папка: \"%1\"",\r
+Logs:\r
+       "Логове",\r
+FileUpload:\r
+       "Качване на файл",\r
+DirEmpty:\r
+       "Няма файлове в \"%1\"",\r
+\r
+// right click menu item directory\r
+// directory\r
+CreateSubDir:\r
+       "Създаване на папка",\r
+DeleteDir:\r
+       "Изтриване",\r
+RenameDir:\r
+       "Преименуване",\r
+\r
+// file\r
+DeleteFile:\r
+       "Изтрий",\r
+RenameFile:\r
+       "Преименувай",\r
+RotateClockwise:\r
+       "Завърти надясно",\r
+RotateAntiClockwise:\r
+       "Завърти наляво",\r
+ResizeImage:\r
+       "Промени големината на картинката",\r
+ChangeCaption:\r
+       "Промени Заглавието",\r
+\r
+// create a file\r
+WhatFilenameToCreateAs:\r
+       "Какъв файл ще създадете?",\r
+AskIfOverwrite:\r
+       "Файлът \"%1\" вече съществува. Да презапиша ли?",\r
+NoForwardslash:\r
+       "\nНе можете да използвате '/' в името на файла",\r
+\r
+// messages management\r
+CreateDirMessage:\r
+       "Създаване на папка в \"%1\":",\r
+DelDirMessage:\r
+       "Сигурни ли сте, че искате да изтриете папката \"%1\"?",\r
+DelFileMessage:\r
+       "Сигурни ли сте, че искате да изтриете файла \"%1\"?",\r
+DelMultipleFilesMessage:\r
+       "Сигурни ли сте, че искате да изтриете тези файлове?\n\n'",\r
+DownloadFileFromMessage:\r
+       "Свали файла от адрес?",\r
+FileSavedAsMessage:\r
+       "Записвате файла като ...",\r
+\r
+// resize file\r
+CurrentSize:\r
+       "Текущ размер: \"%1\" x \"%2\"\n",\r
+NewWidth:\r
+       "Нова Широчина?",\r
+NewWidthConfirmTxt:\r
+       "Нова Широчина: \"%1\"\n",\r
+NewHeight:\r
+       "Нова Височина?",\r
+NewHeightConfirmTxt:\r
+       "Нова Височина: \"%1\"\nПравилно ли е?",\r
+\r
+// log messages\r
+RenamedFile:\r
+       "Преименуван файла \"%1\" на \"%2\".",\r
+DirRefreshed:\r
+       "Актуализиране на папките.",\r
+FilesRefreshed:\r
+       "Актуализиране на файловете.",\r
+NotMoreThanOneFile:\r
+       "грешка: Не можете да изберете повече от един файл",\r
+UnknownPanelState:\r
+       "грешка: Неясно състояние на панела.",\r
+// MissingDirWrapper:\r
+//     "error: missing directory wrapper: \"kfm_directories%1\".",\r
+SetStylesError:\r
+       "грешка: Не можете да промените \"%1\" на \"%2\.",\r
+NoPanel:\r
+       "грешка: Панела \"%1\" не съществува.",\r
+FileSelected:\r
+       "Избрани файлове: \"%1\"",\r
+Log_ChangeCaption:\r
+       "Промяна името от \"%1\" на \"%2\"",\r
+UrlNotValidLog:\r
+       "грешка: URL трябва да започва с \"http:\"",\r
+MovingFilesTo:\r
+       "Преместване на файловете [\"%1\"] в \"%2\"",\r
+\r
+// error messages\r
+DirectoryNameExists:\r
+       "Папка с това име вече съществува.",\r
+FileNameNotAllowd:\r
+       "грешка: Забранен тип на файл.",\r
+CouldNotWriteFile:\r
+       "грешка: Не е записан \"%1\".",\r
+CouldNotRemoveDir:\r
+       "Не мога да изтрия папката.\nУверете се, че е празна",\r
+UrlNotValid:\r
+       "грешка: URL трябва да започва с \"http:\"",\r
+CouldNotDownloadFile:\r
+       "грешка: Не мога да сваля файла \"%1\".",\r
+FileTooLargeForThumb:\r
+       "грешка: Картинката \"%1\" е много голяма за да направя миниатюра. Моля, сменете я с по-малка.",\r
+CouldntReadDir:\r
+       "грешка: не виждам папката",\r
+CannotRenameFile:\r
+       "грешка: не мога да променя \"%1\" на \"%2\"",\r
+FilenameAlreadyExists:\r
+       "грешка: вече същестува файл с това име",\r
+\r
+// new in 0.5\r
+EditTextFile:\r
+       "Редактирай текстов файл",\r
+CloseWithoutSavingQuestion:\r
+       "Сигурни ли сте, че искате да затворите без да запишете?",\r
+CloseWithoutSaving:\r
+       "Затвори без записване",\r
+SaveThenClose:\r
+       "Запиши и след това Затвори",\r
+SaveThenCloseQuestion:\r
+       "Сигурни ли сте, че искате да запазите промените?",\r
+\r
+// new in 0.6\r
+LockPanels:\r
+       "Заключи панелите",\r
+UnlockPanels:\r
+       "Отключи панелите",\r
+CreateEmptyFile:\r
+       "Създай празен файл",\r
+DownloadFileFromUrl:\r
+       "Свали файла от URL",\r
+DirectoryProperties:\r
+       "Свойства на папката",\r
+SelectAll:\r
+       "Избери всичко",\r
+SelectNone:\r
+       "Не избирай",\r
+InvertSelection:\r
+       "Обърни избраното",\r
+LoadingKFM:\r
+       "Зареждане на KFM",\r
+Name:\r
+       "име",\r
+FileDetails:\r
+       "Информация за файла",\r
+Search:\r
+       "Търсене",\r
+IllegalDirectoryName:\r
+       "Това \"%1\" не е коректно име на папка",\r
+RecursiveDeleteWarning:\r
+       "Папката \"%1\" не е празна\n Сигурни ли сте, че искате да я изтриете заедно със съдържанието и?\n*ПРЕДУПРЕЖДЕНИЕ*\n Тази операция е НЕОТМЕНИМА",\r
+RmdirFailed:\r
+       "Неуспешно изтриване на папка \"%1\"",\r
+DirNotInDb:\r
+       "Папката не е в базата данни",\r
+ShowPanel:\r
+       "Покажи панел \"%1\"",\r
+ChangeCaption:\r
+       "Промени заглавието",\r
+NewDirectory:\r
+       "Нова папка",\r
+Upload:\r
+       "Качване",\r
+NewCaptionIsThisCorrect:\r
+       "Ново Заглавие:\n%1\n\nПравилно ли е?",\r
+Close:\r
+       "Затваряне",\r
+Loading:\r
+       "Зареждане",\r
+AreYouSureYouWantToCloseKFM:\r
+       "Сигурни ли сте, че искате да затворите KFM прозореца?",\r
+PleaseSelectFileBeforeRename:\r
+       "Моля, изберете файл преди да опитвате да променяте име.",\r
+RenameOnlyOneFile:\r
+       "В даден момент, можете да преименувате само един файл",\r
+RenameFileToWhat:\r
+       "Преименувай файла \"%1\" на ...",\r
+NoRestrictions:\r
+       "Без рестрикции",\r
+Filename:\r
+       "Име на файл",\r
+Maximise:\r
+       "Максимизиране",\r
+Minimise:\r
+       "Минимизиране",\r
+AllowedFileExtensions:\r
+       "Разрешени типове на файл",\r
+Filesize:\r
+       "Размер на файла",\r
+MoveDown:\r
+       "Премести надолу",\r
+Mimetype:\r
+       "Тип на медия",\r
+MoveUp:\r
+       "Премести нагоре",\r
+Restore:\r
+       "Възстанови",\r
+Caption:\r
+       "Заглавие",\r
+CopyFromURL:\r
+       "Копирай от URL",\r
+ExtractZippedFile:\r
+       "Разархивирай",\r
+\r
+// new in 0.8\r
+ViewImage:\r
+       "Покажи картинката",\r
+ReturnThumbnailToOpener:\r
+       "Подай миниатюра",\r
+AddTagsToFiles:\r
+       "Добави таг на файла",\r
+RemoveTagsFromFiles:\r
+       "Изтрий  таг на файла",\r
+HowWouldYouLikeToRenameTheseFiles:\r
+       "Как искате да преименувате тези файлове?\n\nПример: \"images-***.jpg\" ще преименува файловете на \"images-001.jpg\", \"images-002.jpg\", ...",\r
+YouMustPlaceTheWildcard:\r
+       "Вие трябва да поставите някъде в шаблона на файловите имена заместващия символ *",\r
+YouNeedMoreThan:\r
+       "Трябвят повече от %1 * символа за да се създадат %2 файлови имена",\r
+NoFilesSelected:\r
+       "Няма избрани файлове",\r
+Tags:\r
+       "Тагове",\r
+IfYouUseMultipleWildcards:\r
+       "Ако използвате множество заместващи символи в шаблона на файловите имена, те трябва да бъдат групирани заедно!",\r
+NewCaption:\r
+       "Ново Заглавие",\r
+WhatMaximumSize:\r
+       "Колко да бъде максималния размер?",\r
+CommaSeparated:\r
+       "разделени със запетая",\r
+WhatIsTheNewTag:\r
+       "Какъв да бъде новият таг? За множество тагове, разделете със запетаи.",\r
+WhichTagsDoYouWantToRemove:\r
+       "Кой таг искате да изтриете? Ако са няколко, разделете със запетаи."\r
+\r
+,\r
+// New in 0.9\r
+AllFiles: "all files",\r
+AndNMore: "...and %1 more...",\r
+Browse: "Browse...",\r
+ExtractAfterUpload: "extract after upload",\r
+NotAnImageOrImageDimensionsNotReported: "error: not an image, or image dimensions not reported",\r
+PermissionDeniedCannotDeleteFile: "permission denied: cannot delete file",\r
+RenameTheDirectoryToWhat: "Rename the directory '%1' to what?",\r
+RenamedDirectoryAs: "Renamed '%1' as '%2'",\r
+TheFilenameShouldEndWithN: "The filename should end with %1",\r
+WhatFilenameDoYouWantToUse: "What filename do you want to use?"\r
+\r
+,\r
+// New in 1.0\r
+ZipUpFiles: "zip up files",\r
+Cancel: "cancel"\r
+       , // new in 1.2\r
+       Icons                   : "icons", // used to select mode of file view\r
+       ListView                : "list-view", // used to select mode of file view\r
+       SendToCms               : "send to CMS", // close KFM and return the selected files to the CMS\r
+       CannotMoveDirectory     : "permission denied: cannot move directory",\r
+       LastModified            : "last modified", // part of File Details\r
+       ImageDimensions         : "image dimensions", // part of File Details\r
+       CouldNotMoveFiles       : "error: could not move file[s]",\r
+       CopyFiles               : "copy files", // when dragging files to a directory, two choices appear - "copy files" and "move files"\r
+       MoveFiles               : "move files",\r
+       AboutKfm                : "about KFM",\r
+       Errors                  : "Errors",\r
+       Ok                      : "OK" // as in "OK / Cancel"\r
+}\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/bg.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/bg.php
new file mode 100644 (file)
index 0000000..eb5e00e
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *
+ * File Name: bg.php
+ *  Bulgarian language file.
+ *
+ * File Authors:
+ *  kae@verens.com
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                => "\"%1\" already exists",
+       "errorInvalidID"               => "error: invalid ID",
+       "errorFileIDNotFound"          => "error: file id #%1 not found in database",
+       "bannedFilenameExtension"      => "banned extension in file name",
+       "cannotEditRestrictedExtension"=> "cannot edit \"%1\"\nrestricted by file extension",
+       "cannotMoveIntoSelf"           => "cannot move a directory into its own sub-directory",
+       "cannotRenameFromTo"           => "cannot rename \"%1\" to \"%2\"",
+       "CMSRefusesFileDelete"         => "CMS does not allow \"%1\" to be deleted",
+       "couldNotMoveDirectory"        => "could not move directory \"%1\" to \"%2\"",
+       "couldNotCreateFile"           => "could not write file \"%1\"",
+       "errorSettingFileContent"      => "error setting file content",
+       "failedCreateDirectoryCheck"   => "failed to create directory \"%1\"\ncheck filesystem permissions",
+       "failedRenameDirectory"        => "failed to rename directory",
+       "failedToSaveTmpFile"          => "failure to save tmp file \"%1\" to location \"%2\"",
+       "fileAlreadyExists"            => "a file of that name already exists",
+       "filesCopied"                  => "%1 files copied",
+       "illegalDirectoryName"         => "\"%1\" is an illegal directory name",
+       "illegalFileName"              => "\"%1\" is an illegal file name",
+       "illegalTargetDirectory"       => "illegal target directory \"%1\"",
+       "isNotWritable"                => "\"%1\" is not writable",
+       "missingFileInSelection"       => "missing file in selection",
+       "noDataForFileID"              => "no data for file id \"%1\"",
+       "noDataForDirectoryID"         => "no data for directory id \"%1\"",
+       "noNativeZipCommand"           => "no \"zip\" command found on server",
+       "permissionDeniedUpload"       => "permission denied for upload to this directory",
+       "permissionDeniedCreateDirectory"=>"permission denied: cannot create directory",
+       "permissionDeniedCreateFile"   => "permission denied: cannot create file",
+       "permissionDeniedDeleteDirectory"=>"permission denied: cannot delete directory",
+       "permissionDeniedDeleteFile"   => "permission denied: cannot delete file",
+       "permissionDeniedEditDirectory"=> "permission denied: cannot edit directory",
+       "permissionDeniedEditFile"     => "permission denied: cannot edit file",
+       "permissionDeniedMoveDirectory"=> "permission denied: cannot move directory",
+       "permissionDeniedMoveFile"     => "permission denied: cannot move file",
+       "permissionDeniedRename"       => "permission denied: cannot rename \"%1\"",
+       "permissionDeniedViewFile"     => "permission denied: cannot view file",
+       "searchResults"                => "search results",
+       # 1.2
+       "fileNotCreatedDirUnwritable"    => "\"%1\" could not be created. The directory is not writable",
+       "fileNotDeletedUnwritable"       => "\"%1\" cannot be removed. (file not writable)",
+       "fileNotMovableUnwritable"       => "\"%1\" cannot be moved. (file not writable)",
+       "permissionDeniedManipImage"     => "permission denied: cannot manipulate images",
+       "imageNotWritable"               => "image is not writable",
+       "failedGetFileObject"            => "failed to retrieve File object",
+       "failedGetDirectoryObject"       => "failed to retrieve Directory object",
+       "failedDeleteFile"               => "failed to delete file \"%1\"",
+       "failedMoveFile"                 => "failed to move file \"%1\"",
+       "failedWriteToFile"              => "failed write to file \"%1\"",
+       "failedDownloadFromUrl"        => "failed to download from URL \"%1\""
+       ,
+       "file saved"                     => "file saved",
+       "files deleted"                  => "%1 files deleted",
+       "errorZipContainsBannedFilename" => "error: zip contains a banned filename",
+       "error: filename not allowed"    => "error: filename not allowed",
+       "error: url must begin with http"=> "error: url must begin with http",
+       "UNKNOWN TAG"                    => "UNKNOWN TAG \"%1\"",
+       "error: unzip failed"            => "error: unzip failed"
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/cz.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/cz.js
new file mode 100644 (file)
index 0000000..1eb4ab6
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *     http://kfm.verens.com/
+ *
+ * File Name: cz.js
+ *     Czech language file.
+ *
+ * File Authors:
+ *     Petr Kamenik <me_lobo@centrum.cz>
+ */
+
+kfm.lang={
+AddTagsToFiles: "přídat tagy souboru/souborům",
+AllowedFileExtensions: "povolené přípony souboru",
+AreYouSureYouWantToCloseKFM: "Opravdu chcete zavřít okno s KFM editorem?",
+AskIfOverwrite: "Soubor s názvem \"%1\" již existuje. Přepsat?",
+CouldNotWriteFile: "chyba: nelze zapsat soubor \"%1\".",
+CreateSubDir: "vytvořit podadresář",
+CurrentWorkingDir: "Právě se nacházíte v adresáři: \"%1\"",
+CouldNotRemoveDir: "nemohu odstranit adresář.\nujistěte se, že je prázdný",
+CouldNotDownloadFile: "chyba: nelze stáhnout soubor \"%1\".",
+CouldntReadDir: "chyba: nelze přečíst adresář",
+CreateEmptyFile: "vytvořit prázdný soubor",
+CloseWithoutSavingQuestion: "Opravdu chcete zkončit bez uložení?",
+CloseWithoutSaving: "Zavřit bez uložení",
+CannotRenameFile: "chyba: nelze přejmenovat \"%1\" na \"%2\"",
+ChangeCaption: "změnit popisek",
+CreateDirMessage: "Vytvořit podadresář adresáře \"%1\":",
+CurrentSize: "Současná velikost: \"%1\" x \"%2\"\n",
+ChangeCaption: "Změnit popisek",
+Close: "zavřít",
+Caption: "popisek",
+CommaSeparated: "oddělené čárkou",
+CopyFromURL: "Zkopírovat z url",
+Dir: "ltr", // language direction
+Directories: "Adresáře",
+DeleteFile: "smazat",
+DirEmpty: "v adresáři \"%1\" nebyl nalezen žádný soubor",
+DeleteDir: "smazat",
+DelDirMessage: "Opravdu chcete smazat adresář \"%1\"?",
+DelFileMessage: "Opravdu chcete smazat soubor \"%1\"",
+DelMultipleFilesMessage: "Opravdu chcete smazat tyto soubory?\n\n",
+DownloadFileFromMessage: "Odkud stáhnout soubor?",
+DirRefreshed: "adresáře byly znovu načteny.",
+DirectoryNameExists: "adresář s tímto jménem již existuje.",
+DownloadFileFromUrl: "stáhnout soubor z URL",
+DirectoryProperties: "Vlastnosti adresáře",
+DirNotInDb: "adresář není v databázi",
+ErrorPrefix: "chyba: ",
+EditTextFile: "editovat textový soubor",
+ExtractZippedFile: "Rozbalit zazipovaný soubor",
+FileSavedAsMessage: "Pod jakým názvem uložit soubor?",
+FileUpload: "Nahrávání souborů na server",
+FilesRefreshed: "soubory znovu načteny.",
+FileSelected: "vybraný soubor: \"%1\"",
+FileNameNotAllowd: "chyba: nepovolený název souboru",
+FileTooLargeForThumb: "chyba: \"%1\" je příliš velký k vytvoření náhledu. Prosím nahraďte soubor menší verzí.",
+FilenameAlreadyExists: "chyba: soubor s tímto názvem již existuje",
+FileDetails: "Detaily souboru",
+Filename: "název souboru",
+Filesize: "velikost souboru",
+HowWouldYouLikeToRenameTheseFiles: "Jak chcete přejmenovat tyto soubory?\n\npříklad: \"images-***.jpg\" budou přejmenovány na \"images-001.jpg\", \"images-002.jpg\", ...",
+InvertSelection: "invertovat výběr",
+IfYouUseMultipleWildcards: "Pokud použijete více značek pro výběr souborů, musejí být spojeny dohromady",
+IllegalDirectoryName: "neplatný název adresáře \"%1\"",
+LockPanels: "zamknout panely",
+Loading: "nahrávám",
+LoadingKFM: "nahrávám KFM",
+Log_ChangeCaption: "změnen popisek \"%1\" na \"%2\"",
+Logs: "Logy",
+MovingFilesTo: "přesunuji soubory [\"%1\"] do \"%2\"",
+Maximise: "maximalizovat",
+Minimise: "minimalizovat",
+MoveDown: "přesunout dolů",
+Mimetype: "typ MIME",
+MoveUp: "přesunout nahoru",
+NewCaptionIsThisCorrect: "Nový popisek:\n%1\n\nJe to správně?",
+Name: "název",
+NewDirectory: "Nový adresář",
+NoRestrictions: "bez omezení",
+NoForwardslash: "\nNelze použít '/' ve jméně souboru",
+NewWidth: "Nová šírka?",
+NoPanel: "chyba: panel \"%1\" neexistuje.",
+NewCaption: "Nový popisek",
+NewWidthConfirmTxt: "Nová šírka: \"%1\"\n",
+NewHeight: "Nová výška?",
+NewHeightConfirmTxt: "Nová výška: \"%1\"\n\nJe to správně?",
+NotMoreThanOneFile: "chyba: nelze vybrat více souborů najednou",
+NoFilesSelected: "nebyly vybrány žádné soubory",
+PleaseSelectFileBeforeRename: "Před přejmenováním souboru je třeba vybrat soubor",
+RenameDir: "přejmenovat",
+RenameFile: "přejmenovat",
+RotateClockwise: "otočit ve směru hodinových ručiček",
+RotateAntiClockwise: "otočit proti směru hodinových ručiček",
+ResizeImage: "změnit velikost obrázku",
+RenamedFile: "přejmenovávám soubor \"%1\" na \"%2\".",
+Restore: "obnovit",
+ReturnThumbnailToOpener: "vrátit náhled k editování",
+RenameOnlyOneFile: "Přejmenovat lze jen jeden soubor",
+RecursiveDeleteWarning: "Adresář \"%1\" není prázdný\nChcete jej opravdu smazat včetně obsahu?\n*POZOR* TYTO ZMĚNY JSOU NEVRATNÉ",
+RmdirFailed: "chyba při mazání \"%1\"",
+RenameFileToWhat: "Na co přejmenovat soubor \"%1\"?",
+RemoveTagsFromFiles: "odstranit tagy ze souboru/souborů",
+SetStyleschyba: "chyba: nelze nastavit \"%1\" na \"%2\.",
+SaveThenClose: "Uložit a pak zavřít",
+SaveThenCloseQuestion: "Opravdu chcete uložit všechny změny?",
+SelectAll: "vybrat vše",
+SelectNone: "zrušit výběr",
+Search: "Hledat",
+ShowPanel: "ukázat panel \"%1\"",
+Tags: "tagy",
+UnknownPanelState: "chyba: neznámý stav panelu.",
+UrlNotValidLog: "chyba: URL musí začínat s \"http:\"",
+UnlockPanels: "odemknout panely",
+UrlNotValid: "chyba: URL musí začínat s \"http:\"",
+Upload: "Nahrát",
+ViewImage: "zobrazit obrázek",
+WhatFilenameToCreateAs: "Pod jakým názvem vytvořit soubor?",
+WhatMaximumSize: "Jakou maximální velikost vrátit?",
+WhatIsTheNewTag: "Jaký je nový tag?\nVíce tagů oddělte čárkou.",
+WhichTagsDoYouWantToRemove: "Které tagy chcete odstranit?\nVíce tagů oddělte čárkou.",
+YouMustPlaceTheWildcard: "Do hledaného jména souboru musíte umístit znak *",
+YouNeedMoreThan: "Potřebujete více než %1 * znaků pro vytvoření %2 názvů souborů"
+
+,
+// New in 0.9
+AllFiles: "všechny soubory",
+AndNMore: "...a o %1 více...",
+Browse: "Procházet...",
+ExtractAfterUpload: "rozbalit po nahrání na server",
+NotAnImageOrImageDimensionsNotReported: "chyba: není obrázek, nebo nejsou udány rozměry obrázku",
+PermissionDeniedCannotDeleteFile: "přístup odepřen: nelze smazat soubor",
+RenameTheDirectoryToWhat: "Na co přejmenovat adresář '%1'?",
+RenamedDirectoryAs: "Přejmenován '%1' na '%2'",
+TheFilenameShouldEndWithN: "Název souboru by měl končit %1",
+WhatFilenameDoYouWantToUse: "Jaký název souboru chcete použít?"
+
+,
+// New in 1.0
+ZipUpFiles: "zazipovat soubory",
+Cancel: "storno"
+       , // new in 1.2
+       Icons                   : "icons", // used to select mode of file view
+       ListView                : "list-view", // used to select mode of file view
+       SendToCms               : "send to CMS", // close KFM and return the selected files to the CMS
+       CannotMoveDirectory     : "permission denied: cannot move directory",
+       LastModified            : "last modified", // part of File Details
+       ImageDimensions         : "image dimensions", // part of File Details
+       CouldNotMoveFiles       : "error: could not move file[s]",
+       CopyFiles               : "copy files", // when dragging files to a directory, two choices appear - "copy files" and "move files"
+       MoveFiles               : "move files",
+       AboutKfm                : "about KFM",
+       Errors                  : "Errors",
+       Ok                      : "OK" // as in "OK / Cancel"
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/cz.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/cz.php
new file mode 100644 (file)
index 0000000..71a074b
--- /dev/null
@@ -0,0 +1,75 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *  Toto je první překlad tohoto souboru, jistě budou odlazeny některé chyby.
+ *  This is the first czech translation, check for updates later. 
+ * File Name: cz.php
+ *  Czech language file.
+ *
+ * File Authors:
+ *  kae@verens.com
+ *  me_lobo@centrum.cz 
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                => "\"%1\" již existuje",
+       "errorInvalidID"               => "chyba: neplatné ID",
+       "errorFileIDNotFound"          => "chyba: file id #%1 not found in database",
+       "bannedFilenameExtension"      => "nepovolená přípona souboru",
+       "cannotEditRestrictedExtension"=> "nelze editovat \"%1\"\nzákázáno příponou souboru",
+       "cannotMoveIntoSelf"           => "nelze přesunout adresář do vlastního podadresáře",
+       "cannotRenameFromTo"           => "nelze přejmenovat \"%1\" na \"%2\"",
+       "CMSRefusesFileDelete"         => "Systém nepovoluje smazání souboru/adresáře \"%1\" ",
+       "couldNotMoveDirectory"        => "nelze přesunout adresář \"%1\" to \"%2\"",
+       "couldNotCreateFile"           => "nelze zapsat soubor \"%1\"",
+       "errorSettingFileContent"      => "nelze nastavit obsah souboru",
+       "failedCreateDirectoryCheck"   => "nelze vytvořit adresář \"%1\"\nzkontrolujte oprávnění adresáře",
+       "failedRenameDirectory"        => "nelze přejmenovat adresář",
+       "failedToSaveTmpFile"          => "nelze nahrát dočasný soubor \"%1\" do \"%2\"",
+       "fileAlreadyExists"            => "soubor s tímto názvem již existuje",
+       "filesCopied"                  => "%1 soubor(ů) zkopírován(o)",
+       "illegalDirectoryName"         => "\"%1\" je neplatné jméno adresáře",
+       "illegalFileName"              => "\"%1\" je neplatné jméno souboru",
+       "illegalTargetDirectory"       => "neplatný cílový adresář \"%1\"",
+       "isNotWritable"                => "\"%1\" není určen k zápisu",
+       "missingFileInSelection"       => "ve výběru chybí soubor",
+       "noDataForFileID"              => "žádná data pro soubor id \"%1\"",
+       "noDataForDirectoryID"         => "řádná data pro adresář id \"%1\"",
+       "noNativeZipCommand"           => "na serveru nenalezen příkaz \"zip\"",
+       "permissionDeniedUpload"       => "odepřen přístup k nahrávání do tohoto adresáře",
+       "permissionDeniedCreateDirectory"=>"přístup odepřen: nelze vytvořit adresář",
+       "permissionDeniedCreateFile"   => "přístup odepřen: nelze vytvořit soubor",
+       "permissionDeniedDeleteDirectory"=>"přístup odepřen: nelze smazat adresář",
+       "permissionDeniedDeleteFile"   => "přístup odepřen: nelze smazat soubor",
+       "permissionDeniedEditDirectory"=> "přístup odepřen: nelze editovat adresář",
+       "permissionDeniedEditFile"     => "přístup odepřen: nelze editovat soubor",
+       "permissionDeniedMoveDirectory"=> "přístup odepřen: nelze přesunout adresář",
+       "permissionDeniedMoveFile"     => "přístup odepřen: nelze přesunout soubor",
+       "permissionDeniedRename"       => "přístup odepřen: nelze přejmenovat \"%1\"",
+       "permissionDeniedViewFile"     => "přístup odepřen: nelze zobrazit soubor",
+       "searchResults"                => "vysledky hledani",
+       # 1.2
+       "fileNotCreatedDirUnwritable"    => "\"%1\" could not be created. The directory is not writable",
+       "fileNotDeletedUnwritable"       => "\"%1\" cannot be removed. (file not writable)",
+       "fileNotMovableUnwritable"       => "\"%1\" cannot be moved. (file not writable)",
+       "permissionDeniedManipImage"     => "permission denied: cannot manipulate images",
+       "imageNotWritable"               => "image is not writable",
+       "failedGetFileObject"            => "failed to retrieve File object",
+       "failedGetDirectoryObject"       => "failed to retrieve Directory object",
+       "failedDeleteFile"               => "failed to delete file \"%1\"",
+       "failedMoveFile"                 => "failed to move file \"%1\"",
+       "failedWriteToFile"              => "failed write to file \"%1\"",
+       "failedDownloadFromUrl"        => "failed to download from URL \"%1\""
+       ,
+       "file saved"                     => "file saved",
+       "files deleted"                  => "%1 files deleted",
+       "errorZipContainsBannedFilename" => "error: zip contains a banned filename",
+       "error: filename not allowed"    => "error: filename not allowed",
+       "error: url must begin with http"=> "error: url must begin with http",
+       "UNKNOWN TAG"                    => "UNKNOWN TAG \"%1\"",
+       "error: unzip failed"            => "error: unzip failed"
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/da.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/da.js
new file mode 100644 (file)
index 0000000..ef78b3f
--- /dev/null
@@ -0,0 +1,283 @@
+/**\r
+ *  File Name: da.js\r
+ *    Danish language file.\r
+ *  \r
+ *  File Authors:\r
+ *    Janich Rasmussen - krudt@krudtting.dk\r
+ *    Bo Kamp Dudek    - bo@familiendudek.dk\r
+ */\r
+\r
\r
+kfm.lang=\r
+{\r
+\r
+\r
+Dir:\r
+       "ltr",\r
+ErrorPrefix:\r
+       "Fejl: ",\r
+\r
+Directories:\r
+       "Mapper",\r
+CurrentWorkingDir:\r
+       "Aktuel arbejdsmappe : \"%1\"",\r
+Logs:\r
+       "Logs",\r
+FileUpload:\r
+       "Fil Upload",\r
+DirEmpty:\r
+       "Ingen filer fundet i \"%1\"",\r
+\r
+CreateSubDir:\r
+       "Opret undermappe",\r
+DeleteDir:\r
+       "Slet",\r
+RenameDir:\r
+       "Omdøb",\r
+\r
+DeleteFile:\r
+       "Slet",\r
+RenameFile:\r
+       "Omdøb",\r
+RotateClockwise:\r
+       "Rotér med uret",\r
+RotateAntiClockwise:\r
+       "Rotér mod uret",\r
+ResizeImage:\r
+       "Skalér billede",\r
+ChangeCaption:\r
+       "Rediger billedbeskrivelse",\r
+\r
+WhatFilenameToCreateAs:\r
+       "Hvilken datatype skal filen være?",\r
+AskIfOverwrite:\r
+       "En fil med navnet \"%1\" eksisterer allerede. Overskriv filen?",\r
+NoForwardslash:\r
+       "\nDu må ikke bruge '/' i filnavne",\r
+\r
+CreateDirMessage:\r
+       "Opret en undermappe til \"%1\":",\r
+DelDirMessage:\r
+       "Er du sikker på, at du vil slette mappen \"%1\"?",\r
+DelFileMessage:\r
+       "Er du sikker på, at du vil slette filen \"%1\"",\r
+DelMultipleFilesMessage:\r
+       "Er du sikker på, at du vil slette følgende filer?\n\n'",\r
+DownloadFileFromMessage:\r
+       "Hent fil hvorfra?",     \r
+FileSavedAsMessage:\r
+       "Hvilket filnavn skal filen gemmes under?",\r
+\r
+CurrentSize:\r
+       "Nuværende størrelse: \"%1\" x \"%2\"", \r
+NewWidth:\r
+       "Angiv en ny bredde?",\r
+NewWidthConfirmTxt:\r
+       "Nye bredde bliver: \"%1\"",\r
+NewHeight:\r
+       "Angiv en ny højde?",\r
+NewHeightConfirmTxt:\r
+       "Ny højde bliver: \"%1\"\n\nEr dette korrekt?",\r
+\r
+RenamedFile:\r
+       "Omdøber filen \"%1\" til \"%2\".", \r
+DirRefreshed:\r
+       "Mapper blev opdateret.", \r
+FilesRefreshed:\r
+       "Filer blev opdateret.",\r
+NotMoreThanOneFile:\r
+       "Fejl: Du kan ikke vælge mere end én fil af gangen.",\r
+UnknownPanelState:\r
+       "Fejl: Ukendt Panel status.", \r
+\r
+SetStylesError:\r
+       "Fejl: Kan ikke sætte \"%1\" til \"%2\.", \r
+NoPanel:\r
+       "Fejl: Panelet \"%1\" eksisterer ikke.",\r
+FileSelected:\r
+       "Valgt fil: \"%1\"", \r
+Log_ChangeCaption:\r
+       "Ændrer billedebeskrivelsen for \"%1\" til \"%2\"", \r
+UrlNotValidLog:\r
+       "Fejl: Adressen skal begynde med 'http'", \r
+MovingFilesTo:\r
+       "Flytter filerne [\"%1\"] til \"%2\"", \r
+\r
+DirectoryNameExists:\r
+       "En mappe med samme navn eksisterer allerede.", \r
+FileNameNotAllowd:\r
+       "Fejl: Filnavnet er ikke tilladt.",\r
+CouldNotWriteFile:\r
+       "Fejl: Kunne ikke skrive filen \"%1\".",\r
+CouldNotRemoveDir:\r
+       "Kan ikke slette mappen.\nTjek venligst at mappen er tom.",\r
+UrlNotValid:\r
+       "Fejl: Adressen skal begynde med 'http'", \r
+CouldNotDownloadFile:\r
+       "Fejl: Kunne ikke hente filen \"%1\".",\r
+FileTooLargeForThumb:\r
+       "Fejl: Billedet \"%1\" er for stort til at lave et ikon af. Erstat venligst filen med en mindre version.", \r
+CouldntReadDir:\r
+       "Kunne ikke læse mappen",\r
+CannotRenameFile:\r
+       "Fejl: Kunne ikke omdøbe filen \"%1\" til \"%2\"",\r
+FilenameAlreadyExists:\r
+       "Fejl: En fil med samme navn eksisterer allerede",\r
+\r
+// new in 0.5\r
+EditTextFile:\r
+       "Rediger tekstfil",\r
+CloseWithoutSavingQuestion:\r
+       "Er du sikker på, du vil afslutte uden at gemme ændringerne?",\r
+CloseWithoutSaving:\r
+       "Afslut uden at gemme?",\r
+SaveThenClose:\r
+       "Gem ændringer og afslut",\r
+SaveThenCloseQuestion:\r
+       "Vil du gemme ændringerne?",\r
+\r
+// new in 0.6\r
+LockPanels:\r
+       "Lås paneler",\r
+UnlockPanels:\r
+       "Lås paneler op",\r
+CreateEmptyFile:\r
+       "Opret tom fil",\r
+DownloadFileFromUrl:\r
+       "Hent fil fra URL",\r
+DirectoryProperties:\r
+       "Mappe egenskaber",\r
+SelectAll:\r
+       "Marker alle",\r
+SelectNone:\r
+       "Afmarker valgte",\r
+InvertSelection:\r
+       "Inverter valgte",\r
+LoadingKFM:\r
+       "Loader KFM",\r
+Name:\r
+       "Navn",\r
+FileDetails:\r
+       "Egenskaber",\r
+Search:\r
+       "Søg",\r
+IllegalDirectoryName:\r
+       "Ikke gyldigt mappenavn \"%1\"",\r
+RecursiveDeleteWarning:\r
+       "\"%1\" indeholder filer\nVil du slette mappen og alt indhold?\n*ADVARSEL* DENNE HANDLING KAN IKKE FORTRYDES",\r
+RmdirFailed:\r
+       "Kunne ikke slette mappen \"%1\"",\r
+DirNotInDb:\r
+       "Mappen kunne ikke findes i databasen",\r
+ShowPanel:\r
+       "Vis panel \"%1\"",\r
+ChangeCaption:\r
+       "Ret beskrivelse", \r
+NewDirectory:\r
+       "Ny mappe",\r
+Upload:\r
+       "Upload",\r
+NewCaptionIsThisCorrect:\r
+       "Ny beskrivelse:\n%1\n\nEr dette korrekt?",\r
+Close:\r
+       "Luk",\r
+Loading:\r
+       "Indlæser",\r
+AreYouSureYouWantToCloseKFM:\r
+       "Vil du lukke KFM vinduet?",\r
+PleaseSelectFileBeforeRename:\r
+       "Du skal vælge en fil før du kan omdøbe den",\r
+RenameOnlyOneFile:\r
+       "Du kan kun omdøbe én fil af gangen",\r
+RenameFileToWhat:\r
+       "Omdøb filen \"%1\" til?",\r
+NoRestrictions:\r
+       "Ingen restriktioner",\r
+Filename:\r
+       "Filnavn",\r
+Maximise:\r
+       "Maksimer",\r
+Minimise:\r
+       "Minimer",\r
+AllowedFileExtensions:\r
+       "Tilladte filtyper",\r
+Filesize:\r
+       "Størrelse",\r
+MoveDown:\r
+       "Flyt ned",\r
+Mimetype:\r
+       "MIME Type",\r
+MoveUp:\r
+       "Flyt op",\r
+Restore:\r
+       "Gendan",\r
+Caption:\r
+       "Beskrivelse",\r
+CopyFromURL:\r
+       "Kopiér fra URL",\r
+ExtractZippedFile:\r
+       "Pak zip-fil ud",\r
+\r
+// new in 0.8\r
+ViewImage:\r
+       "Vis billede",\r
+ReturnThumbnailToOpener:\r
+       "Returnér thumbnail til editor",\r
+AddTagsToFiles:\r
+       "Tilføj tags til fil(er)",\r
+RemoveTagsFromFiles:\r
+       "Fjern tags fra fil(er)",\r
+HowWouldYouLikeToRenameTheseFiles:\r
+       "Ønsker du at omdøbe disse filer?\n\nEksempel: \"billede-***.jpg\" vil omdøbe filerne til \"billede-001.jpg\", \"billede-002.jpg\", ...",\r
+YouMustPlaceTheWildcard:\r
+       "Du skal erstatte joker-tegnet * et sted i filnavn-skabelonen",\r
+YouNeedMoreThan:\r
+       "Du behøver mere end %1 * tegn for at oprette %2 filnavne",\r
+NoFilesSelected:\r
+       "Ingen filer markeret",\r
+Tags:\r
+       "Tags",\r
+IfYouUseMultipleWildcards:\r
+       "Hvis du bruger flere joker-tegn i filnavn-skabelonen, skal de være grupperet",\r
+NewCaption:\r
+       "Ny titel",\r
+WhatMaximumSize:\r
+       "Hvilken maksimal størrelse skal returnéres?",\r
+CommaSeparated:\r
+       "Komma-separeret",\r
+WhatIsTheNewTag:\r
+       "Hvad er det nye tag?\nHvis du bruger flere tags, skal du separere med kommaer.",\r
+WhichTagsDoYouWantToRemove:\r
+       "Hvilke tags ønsker du at fjerne?\nHvis du bruger flere tags, skal du separere med kommaer."\r
+\r
+,\r
+// New in 0.9\r
+AllFiles: "all files",\r
+AndNMore: "...and %1 more...",\r
+Browse: "Browse...",\r
+ExtractAfterUpload: "extract after upload",\r
+NotAnImageOrImageDimensionsNotReported: "error: not an image, or image dimensions not reported",\r
+PermissionDeniedCannotDeleteFile: "permission denied: cannot delete file",\r
+RenameTheDirectoryToWhat: "Rename the directory '%1' to what?",\r
+RenamedDirectoryAs: "Renamed '%1' as '%2'",\r
+TheFilenameShouldEndWithN: "The filename should end with %1",\r
+WhatFilenameDoYouWantToUse: "What filename do you want to use?"\r
+\r
+,\r
+// New in 1.0\r
+ZipUpFiles: "zip up files",\r
+Cancel: "cancel"\r
+       , // new in 1.2\r
+       Icons                   : "icons", // used to select mode of file view\r
+       ListView                : "list-view", // used to select mode of file view\r
+       SendToCms               : "send to CMS", // close KFM and return the selected files to the CMS\r
+       CannotMoveDirectory     : "permission denied: cannot move directory",\r
+       LastModified            : "last modified", // part of File Details\r
+       ImageDimensions         : "image dimensions", // part of File Details\r
+       CouldNotMoveFiles       : "error: could not move file[s]",\r
+       CopyFiles               : "copy files", // when dragging files to a directory, two choices appear - "copy files" and "move files"\r
+       MoveFiles               : "move files",\r
+       AboutKfm                : "about KFM",\r
+       Errors                  : "Errors",\r
+       Ok                      : "OK" // as in "OK / Cancel"\r
+}\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/da.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/da.php
new file mode 100644 (file)
index 0000000..1773da8
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *
+ * File Name: da.php
+ *  Danish language file.
+ *
+ * File Authors:
+ *  kae@verens.com
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                => "\"%1\" already exists",
+       "errorInvalidID"               => "error: invalid ID",
+       "errorFileIDNotFound"          => "error: file id #%1 not found in database",
+       "bannedFilenameExtension"      => "banned extension in file name",
+       "cannotEditRestrictedExtension"=> "cannot edit \"%1\"\nrestricted by file extension",
+       "cannotMoveIntoSelf"           => "cannot move a directory into its own sub-directory",
+       "cannotRenameFromTo"           => "cannot rename \"%1\" to \"%2\"",
+       "CMSRefusesFileDelete"         => "CMS does not allow \"%1\" to be deleted",
+       "couldNotMoveDirectory"        => "could not move directory \"%1\" to \"%2\"",
+       "couldNotCreateFile"           => "could not write file \"%1\"",
+       "errorSettingFileContent"      => "error setting file content",
+       "failedCreateDirectoryCheck"   => "failed to create directory \"%1\"\ncheck filesystem permissions",
+       "failedRenameDirectory"        => "failed to rename directory",
+       "failedToSaveTmpFile"          => "failure to save tmp file \"%1\" to location \"%2\"",
+       "fileAlreadyExists"            => "a file of that name already exists",
+       "filesCopied"                  => "%1 files copied",
+       "illegalDirectoryName"         => "\"%1\" is an illegal directory name",
+       "illegalFileName"              => "\"%1\" is an illegal file name",
+       "illegalTargetDirectory"       => "illegal target directory \"%1\"",
+       "isNotWritable"                => "\"%1\" is not writable",
+       "missingFileInSelection"       => "missing file in selection",
+       "noDataForFileID"              => "no data for file id \"%1\"",
+       "noDataForDirectoryID"         => "no data for directory id \"%1\"",
+       "noNativeZipCommand"           => "no \"zip\" command found on server",
+       "permissionDeniedUpload"       => "permission denied for upload to this directory",
+       "permissionDeniedCreateDirectory"=>"permission denied: cannot create directory",
+       "permissionDeniedCreateFile"   => "permission denied: cannot create file",
+       "permissionDeniedDeleteDirectory"=>"permission denied: cannot delete directory",
+       "permissionDeniedDeleteFile"   => "permission denied: cannot delete file",
+       "permissionDeniedEditDirectory"=> "permission denied: cannot edit directory",
+       "permissionDeniedEditFile"     => "permission denied: cannot edit file",
+       "permissionDeniedMoveDirectory"=> "permission denied: cannot move directory",
+       "permissionDeniedMoveFile"     => "permission denied: cannot move file",
+       "permissionDeniedRename"       => "permission denied: cannot rename \"%1\"",
+       "permissionDeniedViewFile"     => "permission denied: cannot view file",
+       "searchResults"                => "search results",
+       # 1.2
+       "fileNotCreatedDirUnwritable"    => "\"%1\" could not be created. The directory is not writable",
+       "fileNotDeletedUnwritable"       => "\"%1\" cannot be removed. (file not writable)",
+       "fileNotMovableUnwritable"       => "\"%1\" cannot be moved. (file not writable)",
+       "permissionDeniedManipImage"     => "permission denied: cannot manipulate images",
+       "imageNotWritable"               => "image is not writable",
+       "failedGetFileObject"            => "failed to retrieve File object",
+       "failedGetDirectoryObject"       => "failed to retrieve Directory object",
+       "failedDeleteFile"               => "failed to delete file \"%1\"",
+       "failedMoveFile"                 => "failed to move file \"%1\"",
+       "failedWriteToFile"              => "failed write to file \"%1\"",
+       "failedDownloadFromUrl"        => "failed to download from URL \"%1\""
+       ,
+       "file saved"                     => "file saved",
+       "files deleted"                  => "%1 files deleted",
+       "errorZipContainsBannedFilename" => "error: zip contains a banned filename",
+       "error: filename not allowed"    => "error: filename not allowed",
+       "error: url must begin with http"=> "error: url must begin with http",
+       "UNKNOWN TAG"                    => "UNKNOWN TAG \"%1\"",
+       "error: unzip failed"            => "error: unzip failed"
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/de.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/de.js
new file mode 100644 (file)
index 0000000..9a14a34
--- /dev/null
@@ -0,0 +1,145 @@
+/*\r
+ * File Name: de.js\r
+ *     German language file.\r
+ *\r
+ * File Authors:\r
+ *     windwerfer\r
+ */\r
+\r
+kfm.lang=\r
+{\r
+       AboutKfm                 : "über KFM",\r
+       AddTagsToFiles           : "Beschreibung zu den/der Datei hinzufügen",\r
+       AllFiles                 : "alle Dateien",\r
+       AllowedFileExtensions    : "erlaubte Dateinamen Erweiterungen",\r
+       AndNMore                 : "...und %1 mehr...",\r
+       AreYouSureYouWantToCloseKFM: "Sind Sie sicher das Sie das KFM Fenster schliessen möchten?",\r
+       AskIfOverwrite           : "Die Datei \"%1\" gibt es bereits. Überschreiben?",\r
+       Browse                   : "Durchsuchen...",\r
+       Cancel                   : "Abbrechen",\r
+       CannotMoveDirectory      : "Zugriff verweigert: Verzeichniss kann nicht verschoben werden",\r
+       CannotRenameFile         : "Fehler: Konnte die Datei \"%1\" nicht nach \"%2\" umbenennen.",\r
+       Caption                  : "Überschrift",\r
+       ChangeCaption            : "Überschrift ändern",\r
+       Close                    : "schliessen",\r
+       CloseWithoutSaving       : "Beenden ohne speichern",\r
+       CloseWithoutSavingQuestion: "Sind Sie sicher, dass Sie ohne speichern beenden möchten?",\r
+       CommaSeparated           : "mit Komma getrennt",\r
+       CopyFiles                : "hierher kopieren", // when dragging files to a directory, two choices appear - "copy files" and "move files"\r
+       CopyFromURL              : "kopieren von URL",\r
+       CouldNotDownloadFile     : "Fehler: Konnte die Datei \"%1\" nicht herunterladen.",\r
+       CouldNotMoveFiles        : "Fehler: konnte die Datei[en] nicht verschieben",\r
+       CouldNotRemoveDir        : "Verzeichnis nicht löschbar.\nBitte stellen Sie sicher das es leer ist.",\r
+       CouldNotWriteFile        : "Fehler: Datei \"%1\" konnte nicht geschrieben werden.",\r
+       CouldntReadDir           : "Konnte das Verzeichnis nicht lesen.",\r
+       CreateSubDir             : "Unterverzeichnis erstellen",\r
+       CreateDirMessage         : "Erstelle ein Unterverzeichnis in \"%1\":",\r
+       CurrentSize              : "Momentane Grösse: \"%1\" x \"%2\"",\r
+       CurrentWorkingDir        : "Momentanes Verzeichnis: \"%1\"",\r
+       CreateEmptyFile          : "erstellen einer leeren Datei",\r
+       Dir                      : "Verzeichnis",\r
+       Directories              : "Verzeichnisse",\r
+       ErrorPrefix              : "Fehler: ",\r
+       Logs                     : "Logs",\r
+       FileUpload               : "Datei Hochladen",\r
+       DirEmpty                 : "Keine Dateien gefunden in \"%1\"",\r
+       DeleteDir                : "löschen",\r
+       RenameDir                : "umbenennen",\r
+       DeleteFile               : "löschen",\r
+       RenameFile               : "umbenennen",\r
+       RotateClockwise          : "im Uhrzeigersinn drehen",\r
+       RotateAntiClockwise      : "gegen Uhrzeigersinn drehen",\r
+       ResizeImage              : "Größe ändern",\r
+       WhatFilenameToCreateAs   : "Was für ein Dateityp soll erstellt werden?",\r
+       NoForwardslash           : "\nEs darf kein '/' in dem Dateinamen vorkommen.",\r
+       DelDirMessage            : "Sind Sie sicher das Sie das Verzeichnis \"%1\" löschen möchten?",\r
+       DelFileMessage           : "Sind Sie sicher das Sie die Datei  \"%1\" löschen möchten?",\r
+       DelMultipleFilesMessage  : "Sind Sie sicher das Sie die folgenden Dateien löschen möchten? \n\n",\r
+       DownloadFileFromMessage  : "Herunterladen der Datei von wo?",\r
+       FileSavedAsMessage       : "Als was soll die Datei gespeichert werden?",\r
+       NewWidth                 : "Neue Breite?",\r
+       NewWidthConfirmTxt       : "Neue Breite: \"%1\"",\r
+       NewHeight                : "Neue Höhe?",\r
+       NewHeightConfirmTxt      : "Neue Höhe: \"%1\"\n\nIst das Richtig?",\r
+       RenamedFile              : "umbenennen der Datei \"%1\" nach \"%2\".",\r
+       DirRefreshed             : "Verzeichnisse neu geladen.",\r
+       FilesRefreshed           : "Dateien neu geladen.",\r
+       NotMoreThanOneFile       : "Fehler: Sie können nicht mehr als eine Datei auf einmal wählen.",\r
+       UnknownPanelState        : "Fehler: Unbekannter Panel Status.",\r
+       SetStylesError           : "Fehler: Kann nicht \"%1\" auf \"%2\ setzen.",\r
+       NoPanel                  : "Fehler: Panel \"%1\" existiert nicht.",\r
+       FileSelected             : "Datei ausgewählt: \"%1\"",\r
+       Log_ChangeCaption: "Verändere Bildunterschrift von \"%1\" nach \"%2\"",\r
+       UrlNotValidLog           : "Fehler: URL muss beginnen mit: http",\r
+       MovingFilesTo            : "Verschiebe Dateien [\"%1\"] nach \"%2\"",\r
+       DirectoryNameExists      : "Ein Verzeichnis mit diesem Namen existiert bereits.",\r
+       FileNameNotAllowd        : "Fehler: Dateiname nicht erlaubt.",\r
+       UrlNotValid              : "Fehler: URL muss beginnen mit: http",\r
+       FileTooLargeForThumb     : "Fehler: Das Bild \"%1\" ist zu gross für ein Thumbnail. Bitte tauschen Sie das Bild mit einer kleiner Version aus.",\r
+       FilenameAlreadyExists    : "Fehler: Eine Datei mit diesem Namen existiert bereits.",\r
+       EditTextFile             : "Text-Datei bearbeiten",\r
+       SaveThenClose            : "Speichern, dann beenden",\r
+       SaveThenCloseQuestion    : "Sind Sie sicher das Sie die Änderungen speichern möchten?",\r
+       LockPanels               : "Panel feststellen",\r
+       UnlockPanels             : "Panel lösen",\r
+       DownloadFileFromUrl      : "speichern einer Datei aus dem Internet",\r
+       DirectoryProperties      : "Verzeichnis Eigenschaften",\r
+       SelectAll                : "alle markieren",\r
+       SelectNone               : "markierung aufheben",\r
+       InvertSelection          : "markierung invertieren",\r
+       LoadingKFM               : "lade KFM",\r
+       Name                     : "Name",\r
+       FileDetails              : "Datei Eigenschaften",\r
+       Search                   : "Suche",\r
+       IllegalDirectoryName     : "Falscher Verzeichnisname \"%1\"",\r
+       RecursiveDeleteWarning   : "\"%1\" ist nicht leer\nSind Sie sicher das Sie das Verzeichnis und seinen gesamten Inhalt löschen möchten?\n*WARNUNG* DAS IST NICHT WIEDER UMKEHRBAR.",\r
+       RmdirFailed              : "Gescheitert beim Versuch das Verzeichnis zu löschen \"%1\"",\r
+       DirNotInDb               : "Verzeichnis nicht in der Datenbank",\r
+       ShowPanel                : "Zeige Panel \"%1\"",\r
+       NewDirectory             : "neues Verzeichnis",\r
+       Upload                   : "Hochladen",\r
+       NewCaptionIsThisCorrect  : "Neue Überschrift:\n%1\n\nIst das so richtig?",\r
+       Loading                  : "laden",\r
+       PleaseSelectFileBeforeRename: "Bitte wählen Sie eine Datei aus bevor Sie sie umbenennen",\r
+       RenameOnlyOneFile        : "Sie können Dateien nur nacheinander umbennen",\r
+       RenameFileToWhat         : "Umbennen der Datei \"%1\" zu was?",\r
+       NoRestrictions           : "keine Einschränkungen",\r
+       Filename                 : "Dateiname",\r
+       Maximise                 : "maximieren",\r
+       Minimise                 : "minimieren",\r
+       Filesize                 : "Dateigrösse",\r
+       MoveDown                 : "nach unten",\r
+       Mimetype                 : "Mimetype",\r
+       MoveUp                   : "nach oben",\r
+       Restore                  : "wiederherstellen",\r
+       ExtractZippedFile        : "entpacken einer Datei",\r
+       ViewImage                : "Bild anzeigen",\r
+       ReturnThumbnailToOpener  : "zurückschicken des Thumbnails an den Öffner",\r
+       RemoveTagsFromFiles      : "Beschreibung(en) der Datei löschen",\r
+       HowWouldYouLikeToRenameTheseFiles: "Wie würdest du die Dateien umbenennen?\n\nBeispiel: \"images-***.jpg\" würde die Dateien zu \"images-001.jpg\" , \"images-002.jpg\", ... umbenennen",\r
+       YouMustPlaceTheWildcard  : "Sie müssen mindestens ein '*' irgendwo in der Zeichenkette unterbringen.",\r
+       YouNeedMoreThan          : "Sie brauchen mehr als %1 '*' Zeichen um %2 Dateinamen zu erstellen.",\r
+       NoFilesSelected          : "keine Dateien ausgewählt",\r
+       Tags                     : "Beschreibung",\r
+       IfYouUseMultipleWildcards : "Wenn mehrerere '*' Zeichen in der Zeichenkette sind, müssen diese aufeinander folgen.",\r
+       NewCaption               : "Neue Überschrift",\r
+       WhatMaximumSize          : "Welche maximale Grösse soll zurückgegeben werden?",\r
+       WhatIsTheNewTag          : "Was ist die neue Beschreibung?\nBei mehren diese mit Kommas trennen.",\r
+       WhichTagsDoYouWantToRemove: "Welche Beschreibung möchten Sie entfernen?\nFür mehrer diese mit Kommas trennen." ,\r
+       ExtractAfterUpload       : "entpacken nach dem Herunterladen",\r
+       NotAnImageOrImageDimensionsNotReported: "Fehler: Keine Bild, oder die Bildgrösse nicht enthalten.",\r
+       PermissionDeniedCannotDeleteFile: "Zugriff verweigert: Datei nicht löschbar",\r
+       RenameTheDirectoryToWhat : "Umbenennen des Verzeichnisses '%1' zu?",\r
+       RenamedDirectoryAs       : "Umbenennen von '%1' nach '%2'",\r
+       TheFilenameShouldEndWithN : "Der Dateiname sollte enden mit %1",\r
+       WhatFilenameDoYouWantToUse: "Welchen Dateinamen möchten Sie benutzen?" ,\r
+       ZipUpFiles               : "zippen der Dateien",\r
+       Icons                    : "Icons", // used to select mode of file view\r
+       ListView                 : "Listen ansicht", // used to select mode of file view\r
+       SendToCms                : "ans CMS senden", // close KFM and return the selected files to the CMS\r
+       LastModified             : "zuletzt geändert", // part of File Details\r
+       ImageDimensions          : "Bildgrösse", // part of File Details\r
+       MoveFiles                : "hierher verschieben",\r
+       Errors                   : "Fehler",\r
+       Ok                       : "OK" // as in "OK / Cancel"\r
+}\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/de.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/de.php
new file mode 100644 (file)
index 0000000..cd20dfe
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *
+ * File Name: en.php
+ *  English language file.
+ *
+ * File Authors:
+ *  kae@verens.com
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                  => "\"%1\" existiert bereits",
+       "error: filename not allowed"    => "Fehler: Dateiname ist nicht erlaubt",
+       "error: unzip failed"            => "Fehler: entpacken fehlgeschlagen",
+       "error: url must begin with http"=> "Fehler: URL muss mit http beginnen",
+       "errorInvalidID"                 => "Error: unzulässige ID",
+       "errorFileIDNotFound"            => "Error: die Datei ID #%1 wurde in der Datenbank nicht gefunden",
+       "errorZipContainsBannedFilename" => "Fehler: Zip beinhaltet eine verbotenen Dateinamen",
+       "bannedFilenameExtension"        => "verbotene Dateinamenerweiterung",
+       "cannotEditRestrictedExtension"  => "konnte \"%1\" nicht bearbeiten\nwegen Dateierweiterungsbeschrenkung",
+       "cannotMoveIntoSelf"             => "ich kann ein Verzeichniss nicht in sein eigenes Unterverzeichnis verschieben",
+       "cannotRenameFromTo"             => "kann \"%1\" nicht zu  \"%2\" umbenennen",
+       "CMSRefusesFileDelete"           => "CMS erlaubt es nicht \"%1\" zu löschen",
+       "couldNotMoveDirectory"          => "konnte das Verzeichnis \"%1\" nicht nach \"%2\" verschieben",
+       "couldNotCreateFile"             => "konnte die Datei \"%1\" nicht erstellen",
+       "errorSettingFileContent"        => "Fehler beim erstellen des Dateiinhalts",
+       "failedCreateDirectoryCheck"     => "Fehler beim Erstellen des Verzeichnisses \"%1\"\nÜberprüfen Sie die Zugriffsrechte",
+       "failedDeleteFile"               => "unfähig die Datei \"%1\" zu löschen",
+       "failedDownloadFromUrl"          => "unfähig die Datei \"%1\" von der URL zu laden",
+       "failedGetDirectoryObject"       => "Ordnerobjekt nicht erhalten",
+       "failedGetFileObject"            => "Dateiobjekt nicht erhalten",
+       "failedMoveFile"                 => "unfähig die Datei \"%1\" zu verschieben",
+       "failedRenameDirectory"          => "Fehler beim Umbenennen des Verzeichnisses",
+       "failedToSaveTmpFile"            => "Fehler beim speichern der tmp Datei \"%1\" nach \"%2\"",
+       "failedWriteToFile"              => "unfähig in die Datei \"%1\" zu schreiben",
+       "file saved"                     => "Datei gespeichert",
+       "fileAlreadyExists"              => "eine Datei mit diesem Namen existiert bereis",
+       "fileNotCreatedDirUnwritable"    => "\"%1\" konnte nicht erstellt werden. Das Verzeichnis ist schreibgeschützt",
+       "fileNotDeletedUnwritable"       => "\"%1\" kann nicht entfernt werden. (Datei ist schreibgeschützt)",
+       "fileNotMovableUnwritable"       => "\"%1\" kann nicht verschoben werden. (Datei ist schreibgeschützt)",
+       "files deleted"                  => "%1 Dateien gelöscht",
+       "filesCopied"                    => "%1 Dateien kopiert",
+       "illegalDirectoryName"           => "\"%1\" ist ein illegaler Verzeichnisname",
+       "illegalFileName"                => "\"%1\" ist ein illegaler Dateiname",
+       "illegalTargetDirectory"         => "illegales Zielverzeichnis \"%1\"",
+       "imageNotWritable"               => "Bild ist schreibgeschützt",
+       "isNotWritable"                  => "\"%1\" ist nicht Schreibbar",
+       "missingFileInSelection"         => "Verlorene Datei in der Auswahl",
+       "noDataForFileID"                => "keine Daten für Datei-ID \"%1\"",
+       "noDataForDirectoryID"           => "keine Daten für Verzeichnis-ID \"%1\"",
+       "noNativeZipCommand"             => "kein \"zip\" Commando auf dem Server gefunden",
+       "permissionDeniedUpload"         => "Zugriff verweigert für das Hochladen in dieses Verzeichnis",
+       "permissionDeniedCreateDirectory"=>"Zugriff verweigert: kann das Verzeichnis nicht erstellen",
+       "permissionDeniedCreateFile"     => "Zugriff verweigert: kann die Datei nicht erstellen",
+       "permissionDeniedDeleteDirectory"=>"Zugriff verweigert: kann das Verzeichnis nicht löschen",
+       "permissionDeniedDeleteFile"     => "Zugriff verweigert: kann die Datei nicht löschen",
+       "permissionDeniedEditDirectory"  => "Zugriff verweigert: kann das Verzeichnis nicht bearbeiten",
+       "permissionDeniedEditFile"       => "Zugriff verweigert: kann die Datei nicht bearbeiten",
+       "permissionDeniedManipImage"     => "Zugriff verweigert: Bild kann nicht verändert werden",
+       "permissionDeniedMoveDirectory"  => "Zugriff verweigert: kann das Verzeichnis nicht verschieben",
+       "permissionDeniedMoveFile"       => "Zugriff verweigert: kann die Datei nicht verschieben",
+       "permissionDeniedRename"         => "Zugriff verweigert: kann \"%1\" nicht umbenennen",
+       "permissionDeniedViewFile"       => "Zugriff verweigert: kann die Datei nicht anzeigen",
+       "searchResults"                  => "Suchergebnisse",
+       "UNKNOWN TAG"                    => "UNBEKANNTE BESCHREIBUNG \"%1\""
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/en.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/en.js
new file mode 100644 (file)
index 0000000..d935cd3
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *     http                    ://kfm.verens.com/
+ *
+ * File Name: en.js
+ *     English language file.
+ *
+ * File Authors:
+ *     kae@verens.com
+ */
+
+kfm.lang={
+       AddTagsToFiles          : "add tags to file(s)",
+       AllFiles                : "all files",
+       AllowedFileExtensions   : "allowed file extensions",
+       AndNMore                : "...and %1 more...",
+       AreYouSureYouWantToCloseKFM: "Are you sure you want to close the KFM window?",
+       AskIfOverwrite          : "The file \"%1\" already exists. Overwrite?",
+       Browse                  : "Browse...",
+       Cancel                  : "cancel",
+       CouldNotWriteFile       : "error: could not write file \"%1\".",
+       CreateSubDir            : "create sub-directory",
+       CurrentWorkingDir       : "Current Working Directory: \"%1\"",
+       CouldNotRemoveDir       : "cannot remove directory.\nplease make sure it is empty",
+       CouldNotDownloadFile    : "error: could not download file \"%1\".",
+       CouldntReadDir          : "error: couldn't read directory",
+       CreateEmptyFile         : "create empty file",
+       CloseWithoutSavingQuestion: "Are you sure you want to close without saving?",
+       CloseWithoutSaving      : "Close Without Saving",
+       CannotRenameFile        : "error: cannot rename \"%1\" to \"%2\"",
+       ChangeCaption           : "change caption",
+       CreateDirMessage        : "Create a sub-directory of \"%1\":",
+       CurrentSize             : "Current Size: \"%1\" x \"%2\"\n",
+       ChangeCaption           : "Change Caption",
+       Close                   : "close",
+       Caption                 : "caption",
+       CommaSeparated          : "comma-separated",
+       CopyFromURL             : "Copy from URL",
+       Dir                     : "ltr", // language direction
+       Directories             : "Directories",
+       DeleteFile              : "delete",
+       DirEmpty                : "no files found in \"%1\"",
+       DeleteDir               : "delete",
+       DelDirMessage           : "Are you sure you want to delete the directory \"%1\"?",
+       DelFileMessage          : "Are you sure you want to delete the file \"%1\"",
+       DelMultipleFilesMessage : "Are you sure you want to delete the following files?\n\n",
+       DownloadFileFromMessage : "Download file from where?",
+       DirRefreshed            : "directories refreshed.",
+       DirectoryNameExists     : "a directory of that name already exists.",
+       DownloadFileFromUrl     : "download file from URL",
+       DirectoryProperties     : "Directory Properties",
+       DirNotInDb              : "directory not in database",
+       ErrorPrefix             : "error: ",
+       EditTextFile            : "edit text file",
+       ExtractAfterUpload      : "extract after upload",
+       ExtractZippedFile       : "Extract zipped file",
+       FileSavedAsMessage      : "What should the file be saved as?",
+       FileUpload              : "File Upload",
+       FilesRefreshed          : "files refreshed.",
+       FileSelected            : "file selected: \"%1\"",
+       FileNameNotAllowd       : "error: filename not allowed",
+       FileTooLargeForThumb    : "error: \"%1\" is too large to make a thumbnail. Please replace the file with a smaller version.",
+       FilenameAlreadyExists   : "error: a file of that name already exists",
+       FileDetails             : "File Details",
+       Filename                : "filename",
+       Filesize                : "filesize",
+       HowWouldYouLikeToRenameTheseFiles: "How would you like to rename these files?\n\nexample: \"images-***.jpg\" will rename files to \"images-001.jpg\", \"images-002.jpg\", ...",
+       InvertSelection         : "invert selection",
+       IfYouUseMultipleWildcards: "If you use multiple wildcards in the filename template, they must be grouped together",
+       IllegalDirectoryName    : "illegal directory name \"%1\"",
+       LockPanels              : "lock panels",
+       Loading                 : "loading",
+       LoadingKFM              : "loading KFM",
+       Log_ChangeCaption: "changing caption of \"%1\" to \"%2\"",
+       Logs                    : "Logs",
+       MovingFilesTo           : "moving files [\"%1\"] to \"%2\"",
+       Maximise                : "maximise",
+       Minimise                : "minimise",
+       MoveDown                : "move down",
+       Mimetype                : "mimetype",
+       MoveUp                  : "move up",
+       NewCaptionIsThisCorrect : "New Caption:\n%1\n\nIs this correct?",
+       Name                    : "name",
+       NewDirectory            : "New Directory",
+       NoRestrictions          : "no restrictions",
+       NoForwardslash          : "\nYou may not use '/' in the filename",
+       NewWidth                : "New Width?",
+       NoPanel                 : "error: panel \"%1\" doesn\'t exist.",
+       NotAnImageOrImageDimensionsNotReported: "error: not an image, or image dimensions not reported",
+       NewCaption              : "New Caption",
+       NewWidthConfirmTxt      : "New Width: \"%1\"\n",
+       NewHeight               : "New Height?",
+       NewHeightConfirmTxt     : "New Height: \"%1\"\n\nIs this correct?",
+       NotMoreThanOneFile      : "error: you cannot choose more than one file at a time",
+       NoFilesSelected         : "no files selected",
+       PermissionDeniedCannotDeleteFile: "permission denied: cannot delete file",
+       PleaseSelectFileBeforeRename: "Please select a file before you try to rename it",
+       RenameDir               : "rename",
+       RenameFile              : "rename",
+       RotateClockwise         : "rotate clock-wise",
+       RotateAntiClockwise     : "rotate anti-clockwise",
+       ResizeImage             : "resize image",
+       RenamedFile             : "renaming file \"%1\" to \"%2\".",
+       Restore                 : "restore",
+       ReturnThumbnailToOpener : "return thumbnail to editor",
+       RenameOnlyOneFile       : "You can only rename one file at a time",
+       RecursiveDeleteWarning  : "\"%1\" is not empty\nAre you sure you want to delete it and all its contents?\n*WARNING* THIS IS NOT REVERSIBLE",
+       RmdirFailed             : "failed to delete directory \"%1\"",
+       RenamedDirectoryAs      : "Renamed '%1' as '%2'",
+       RenameFileToWhat        : "Rename the file \"%1\" to what?",
+       RenameTheDirectoryToWhat: "Rename the directory '%1' to what?",
+       RemoveTagsFromFiles     : "remove tags from file(s)",
+       SetStylesError          : "error: cannot set \"%1\" to \"%2\.",
+       SaveThenClose           : "Save, then Close",
+       SaveThenCloseQuestion   : "Are you sure you want to save the changes you made?",
+       SelectAll               : "select all",
+       SelectNone              : "select none",
+       Search                  : "Search",
+       ShowPanel               : "show panel \"%1\"",
+       Tags                    : "tags",
+       TheFilenameShouldEndWithN: "The filename should end with %1",
+       UnknownPanelState       : "error: unknown panel state.",
+       UrlNotValidLog          : "error: URL must begin with \"http:\"",
+       UnlockPanels            : "unlock panels",
+       UrlNotValid             : "error: URL must begin with \"http:\"",
+       Upload                  : "Upload",
+       ViewImage               : "view image",
+       WhatFilenameDoYouWantToUse: "What filename do you want to use?",
+       WhatFilenameToCreateAs  : "What should the file be created as?",
+       WhatMaximumSize         : "What maximum size should be returned?",
+       WhatIsTheNewTag         : "What is the new tag?\nFor multiple tags, separate by commas.",
+       WhichTagsDoYouWantToRemove: "Which tags do you want to remove?\nFor multiple tags, separate by commas.",
+       YouMustPlaceTheWildcard : "You must place the wildcard character * somewhere in the filename template",
+       YouNeedMoreThan         : "You need more than %1 * characters to create %2 filenames",
+       ZipUpFiles              : "zip up files"
+       , // new in 1.2
+       Icons                   : "icons", // used to select mode of file view
+       ListView                : "list-view", // used to select mode of file view
+       SendToCms               : "send to CMS", // close KFM and return the selected files to the CMS
+       CannotMoveDirectory     : "permission denied: cannot move directory",
+       LastModified            : "last modified", // part of File Details
+       ImageDimensions         : "image dimensions", // part of File Details
+       CouldNotMoveFiles       : "error: could not move file[s]",
+       CopyFiles               : "copy files", // when dragging files to a directory, two choices appear - "copy files" and "move files"
+       MoveFiles               : "move files",
+       AboutKfm                : "about KFM",
+       Errors                  : "Errors",
+       Ok                      : "OK" // as in "OK / Cancel"
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/en.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/en.php
new file mode 100644 (file)
index 0000000..a101f17
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *
+ * File Name: en.php
+ *  English language file.
+ *
+ * File Authors:
+ *  kae@verens.com
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                  => "\"%1\" already exists",
+       "errorInvalidID"                 => "error: invalid ID",
+       "errorFileIDNotFound"            => "error: file id #%1 not found in database",
+       "bannedFilenameExtension"        => "banned extension in file name",
+       "cannotEditRestrictedExtension"  => "cannot edit \"%1\"\nrestricted by file extension",
+       "cannotMoveIntoSelf"             => "cannot move a directory into its own sub-directory",
+       "cannotRenameFromTo"             => "cannot rename \"%1\" to \"%2\"",
+       "CMSRefusesFileDelete"           => "CMS does not allow \"%1\" to be deleted",
+       "couldNotMoveDirectory"          => "could not move directory \"%1\" to \"%2\"",
+       "couldNotCreateFile"             => "could not write file \"%1\"",
+       "errorSettingFileContent"        => "error setting file content",
+       "failedCreateDirectoryCheck"     => "failed to create directory \"%1\"\ncheck filesystem permissions",
+       "failedRenameDirectory"          => "failed to rename directory",
+       "failedToSaveTmpFile"            => "failure to save tmp file \"%1\" to location \"%2\"",
+       "fileAlreadyExists"              => "a file of that name already exists",
+       "filesCopied"                    => "%1 files copied",
+       "illegalDirectoryName"           => "\"%1\" is an illegal directory name",
+       "illegalFileName"                => "\"%1\" is an illegal file name",
+       "illegalTargetDirectory"         => "illegal target directory \"%1\"",
+       "isNotWritable"                  => "\"%1\" is not writable",
+       "missingFileInSelection"         => "missing file in selection",
+       "noDataForFileID"                => "no data for file id \"%1\"",
+       "noDataForDirectoryID"           => "no data for directory id \"%1\"",
+       "noNativeZipCommand"             => "no \"zip\" command found on server",
+       "permissionDeniedUpload"         => "permission denied for upload to this directory",
+       "permissionDeniedCreateDirectory"=> "permission denied: cannot create directory",
+       "permissionDeniedCreateFile"     => "permission denied: cannot create file",
+       "permissionDeniedDeleteDirectory"=> "permission denied: cannot delete directory",
+       "permissionDeniedDeleteFile"     => "permission denied: cannot delete file",
+       "permissionDeniedEditDirectory"  => "permission denied: cannot edit directory",
+       "permissionDeniedEditFile"       => "permission denied: cannot edit file",
+       "permissionDeniedMoveDirectory"  => "permission denied: cannot move directory",
+       "permissionDeniedMoveFile"       => "permission denied: cannot move file",
+       "permissionDeniedRename"         => "permission denied: cannot rename \"%1\"",
+       "permissionDeniedViewFile"       => "permission denied: cannot view file",
+       "searchResults"                  => "search results",
+       # 1.2
+       "fileNotCreatedDirUnwritable"    => "error: \"%1\" could not be created. The directory is not writable",
+       "fileNotDeletedUnwritable"       => "error: \"%1\" cannot be removed. (file not writable)",
+       "fileNotMovableUnwritable"       => "error: \"%1\" cannot be moved. (file not writable)",
+       "permissionDeniedManipImage"     => "error: permission denied: cannot manipulate images",
+       "imageNotWritable"               => "error: image is not writable",
+       "failedGetFileObject"            => "error: failed to retrieve File object",
+       "failedGetDirectoryObject"       => "error: failed to retrieve Directory object",
+       "failedDeleteFile"               => "error: failed to delete file \"%1\"",
+       "failedMoveFile"                 => "error: failed to move file \"%1\"",
+       "failedWriteToFile"              => "error: failed write to file \"%1\"",
+       "failedDownloadFromUrl"          => "error: failed to download from URL \"%1\""
+       ,
+       "file saved"                     => "file saved",
+       "files deleted"                  => "%1 files deleted",
+       "errorZipContainsBannedFilename" => "error: zip contains a banned filename",
+       "error: filename not allowed"    => "error: filename not allowed",
+       "error: url must begin with http"=> "error: url must begin with http",
+       "UNKNOWN TAG"                    => "UNKNOWN TAG \"%1\"",
+       "error: unzip failed"            => "error: unzip failed"
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/es.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/es.js
new file mode 100755 (executable)
index 0000000..2c5dbba
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Licensed under the terms of the GNU Lesser General Public License:
+ *     http:
+ *
+ * For further information visit:
+ *     http:
+ *
+ * File Name: es.js
+ *     Spanish (latin-american) language file.
+ *
+ * File Authors:
+ *  Ramón Ramos (arathael@gmail.com)
+ *
+ * Last Updated:
+ *  25/05/2007
+ */
+
+kfm.lang=
+{
+Dir: "ltr", 
+ErrorPrefix: "error: ",
+Directories: "Directorios",
+CurrentWorkingDir: "Directorio actual: \"%1\"",
+Logs: "Registros",
+FileUpload: "Subir archivo",
+DirEmpty: "no se encontraron archivos en \"%1\"",
+CreateSubDir: "crear sub-directorio",
+DeleteDir: "eliminar",
+RenameDir: "renombrar",
+DeleteFile: "eliminar",
+RenameFile: "renombrar",
+RotateClockwise: "girar en sentido a las manecillas del reloj",
+RotateAntiClockwise: "girar en sentido inverso a las manecillas del reloj",
+ResizeImage: "redimensionar imagen",
+ChangeCaption: "cambiar etiqueta",
+FileName: "¿Nombre del nuevo archivo?",
+AskIfOverwrite: "El archivo \"%1\" ya existe. ¿Sobreescribir?",
+NoForwardslash: "\nNo puedes utilizar '/' en el nombre del archivo",
+CreateDirMessage: "Crear un sub-directorio en \"%1\":",
+DelDirMessage: "¿Estás seguro de eliminar el directorio \"%1\"?",
+DelFileMessage: "¿Estás seguro de eliminar el archivo \"%1\"",
+DelMultipleFilesMessage: "¿Estás seguro de eliminar estos archivos?\n\n'",
+DownloadFileFromMessage: "¿De donde se descargará el archivo?",
+FileSavedAsMessage: "Con que nombre se deberá guardar el archivo?",
+CurrentSize: "Dimensiones actuales: \"%1\" x \"%2\"\n",
+NewWidth: "¿Nuevo ancho?",
+NewWidthConfirmTxt: "Nuevo ancho establecido: \"%1\"\n",
+NewHeight: "¿Nueva altura?",
+NewHeightConfirmTxt: "Nueva altura establecida: \"%1\"\n\n¿Es esto correcto?",
+RenamedFile: "Archivo \"%1\" renombrado a \"%2\".",
+DirRefreshed: "directorios actualizados.",
+FilesRefreshed: "archivos actualizados.",
+NotMoreThanOneFile: "error: no puedes seleccionar más de un archivo a la vez.",
+UnknownPanelState: "error: estado de panel desconocido.",
+SetStylesError:
+       "error: no se puede renombrar \"%1\" a \"%2\.",
+NoPanel:
+       "error: el panel \"%1\" no existe.",
+FileSelected:
+       "archivo seleccionado: \"%1\"",
+Log_ChangeCaption:
+       "cambiando etiqueta de \"%1\" a \"%2\"",
+UrlNotValidLog:
+       "error: los URLs deben de comenzar con \"http:\"",
+MovingFilesTo:
+       "moviendo archivos [\"%1\"] a \"%2\"",
+
+DirectoryNameExists:
+       "ya existe un directorio con ese nombre.",
+FileNameNotAllowd:
+       "error: nombre de archivo no permitido",
+CouldNotWriteFile:
+       "error: no se pudo escribir el archivo \"%1\".",
+CouldNotRemoveDir:
+       "no se pudo eliminar el directorio.\nporfavor asegúrate de que está vacío",
+UrlNotValid:
+       "error: los URLs debe de comenzar con \"http:\"",
+CouldNotDownloadFile:
+       "error: no se pudo descargar el archivo \"%1\".",
+FileTooLargeForThumb:
+       "error: \"%1\" es muy grande para generar una miniatura. Porfavor reemplaza el archivo con una versión más pequeña.",
+CouldntReadDir:
+       "error: no se pudo leer el directorio",
+CannotRenameFile:
+       "error: no se pudo renombrar \"%1\" a \"%2\"",
+FilenameAlreadyExists:
+       "error: ya existe un archivo con ese nombre",
+
+// new in 0.5
+EditTextFile:
+       "editar archivo de texto",
+CloseWithoutSavingQuestion:
+       "¿Salir sin guardar los cambios?",
+CloseWithoutSaving:
+       "Cerrar sin guardar los cambios",
+SaveThenClose:
+       "Guardar y cerrar",
+SaveThenCloseQuestion:
+       "¿Guardar los cambios?",
+
+// new in 0.6
+LockPanels:
+       "bloquear paneles",
+UnlockPanels:
+       "desbloquear paneles",
+CreateEmptyFile:
+       "crear archivo vacío",
+DownloadFileFromUrl:
+       "descargar archivo desde ubicación",
+DirectoryProperties:
+       "Propiedades de carpeta",
+SelectAll:
+       "seleccionar todo",
+SelectNone:
+       "deseleccionar",
+InvertSelection:
+       "invertir selección",
+LoadingKFM:
+       "cargando KFM",
+Name:
+       "nombre",
+FileDetails:
+       "Detalles de archivo",
+Search:
+       "Buscar",
+IllegalDirectoryName:
+       "nombre inválido de directorio \"%1\"",
+RecursiveDeleteWarning:
+       "\"%1\" no está vacio\nEstás seguro de eliminarlo junto con todos sus archivos?\n*ADVERTENCIA* Esto no es reversible",
+RmdirFailed:
+       "fallo al eliminar directorio \"%1\"",
+DirNotInDb:
+       "directorio no se encuentra en la base de datos",
+ShowPanel:
+       "mostrar panel \"%1\"",
+ChangeCaption:
+       "Cambiar etiqueta",
+NewDirectory:
+       "Nuevo directorio",
+Upload:
+       "Subir",
+NewCaptionIsThisCorrect:
+       "Nueva Etiqueta:\n%1\n\n¿Está correcto?",
+Close:
+       "cerrar",
+Loading:
+       "cargando",
+AreYouSureYouWantToCloseKFM:
+       "Está seguro de cerrar la ventana de KFM?",
+PleaseSelectFileBeforeRename:
+       "Porfavor seleccione un archivo antes de renombrarlo",
+RenameOnlyOneFile:
+       "Solo puede renombrar un archivo a la vez",
+RenameFileToWhat:
+       "Renombrar el archivo \"%1\" a que?",
+NoRestrictions:
+       "sin restricciones",
+Filename:
+       "nombre de archivo",
+Maximise:
+       "maximizar",
+Minimise:
+       "minimizar",
+AllowedFileExtensions:
+       "extensiones de archivo permitidas",
+Filesize:
+       "tamaño de archivo",
+MoveDown:
+       "mover abajo",
+Mimetype:
+       "tipo mime",
+MoveUp:
+       "mover arriba",
+Restore:
+       "restaurar",
+Caption:
+       "etiqueta",
+CopyFromURL:
+       "Copiar desde URL",
+ExtractZippedFile:
+       "Extraer archivo comprimido",
+
+// new in 0.8
+ViewImage:
+       "ver imagen",
+ReturnThumbnailToOpener:
+       "regresar miniatura a lanzador",
+AddTagsToFiles:
+       "agregar tags de archivo(s)",
+RemoveTagsFromFiles:
+       "quitaqr tags de archivo(s)",
+HowWouldYouLikeToRenameTheseFiles:
+       "Como renombrar estos archivos?\n\nejemplo: \"imagenes-***.jpg\" se renombrarán a \"imagenes-001.jpg\", \"imagenes-002.jpg\", ...",
+YouMustPlaceTheWildcard:
+       "Debes colocar el carácter comodin * en la plantilla del nombre de archivo",
+YouNeedMoreThan:
+       "Nececitas más de %1 caracteres * para crear %2 nombres de archivo",
+NoFilesSelected:
+       "ningun archivo seleccionado",
+Tags:
+       "tags",
+IfYouUseMultipleWildcards:
+       "Si utilizas multiples comodines en la plantilla de nombre de archivo, deben de estar juntos",
+NewCaption:
+       "Nueva etiqueta",
+WhatMaximumSize:
+       "¿Que tamaño máximo de archivo debe devolverse?",
+CommaSeparated:
+       "separados-por-coma",
+WhatIsTheNewTag:
+       "¿Cual es el nuevo tag?\nPara múltiples tags, separar con comas.",
+WhichTagsDoYouWantToRemove:
+       "¿Qué tags desea quitar?\nPara múltiples tags, separar por comas."
+
+,
+// New in 0.9
+AllFiles: "todos los archivos",
+AndNMore: "...y %1 más...",
+Browse: "Examinar...",
+ExtractAfterUpload: "extraer despues de subir",
+NotAnImageOrImageDimensionsNotReported: "error: no es una imagen, o no se encuentran las dimensiones de la imagen",
+PermissionDeniedCannotDeleteFile: "permiso denegado: no se puede eliminar el archivo",
+RenameTheDirectoryToWhat: "¿Renombrar el directorio '%1' a que?",
+RenamedDirectoryAs: "'%1' renombrado como '%2'",
+TheFilenameShouldEndWithN: "El nombre de archivo debe terminar con %1",
+WhatFilenameDoYouWantToUse: "¿Qué nombre de archivo desea utilizar?"
+
+,
+// New in 1.0
+ZipUpFiles: "comprimir archivos (en zip)",
+Cancel: "cancelar"
+       , // new in 1.2
+       Icons                   : "icons", // used to select mode of file view
+       ListView                : "list-view", // used to select mode of file view
+       SendToCms               : "send to CMS", // close KFM and return the selected files to the CMS
+       CannotMoveDirectory     : "permission denied: cannot move directory",
+       LastModified            : "last modified", // part of File Details
+       ImageDimensions         : "image dimensions", // part of File Details
+       CouldNotMoveFiles       : "error: could not move file[s]",
+       CopyFiles               : "copy files", // when dragging files to a directory, two choices appear - "copy files" and "move files"
+       MoveFiles               : "move files",
+       AboutKfm                : "about KFM",
+       Errors                  : "Errors",
+       Ok                      : "OK" // as in "OK / Cancel"
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/es.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/es.php
new file mode 100644 (file)
index 0000000..9f1e263
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *
+ * File Name: es.php
+ *  Spanish language file.
+ *
+ * File Authors:
+ *  kae@verens.com
+ *  arathael@gmail.com
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                => "\"%1\" ya existe",
+       "errorInvalidID"               => "error: ID invalido",
+       "errorFileIDNotFound"          => "error: id del archivo #%1 no encontrado en la base de datos",
+       "bannedFilenameExtension"      => "extensión prohibida en el nombre de archivo",
+       "cannotEditRestrictedExtension"=> "imposible editar \"%1\"\nrestringido por la extensión de archivo",
+       "cannotMoveIntoSelf"           => "no se puede mover un directorio hacia un subdirectorio del mismo",
+       "cannotRenameFromTo"           => "imposible renombrar \"%1\" a \"%2\"",
+       "CMSRefusesFileDelete"         => "CMS no permite borrar \"%1\"",
+       "couldNotMoveDirectory"        => "no se puede mover el directorio \"%1\" a \"%2\"",
+       "couldNotCreateFile"           => "no se puede escribir al archivo \"%1\"",
+       "errorSettingFileContent"      => "error estableciendo contenido del archivo",
+       "failedCreateDirectoryCheck"   => "fallo al crear el directorio \"%1\"\nrevisar los permisos del sistema de archivos",
+       "failedRenameDirectory"        => "no se pudo renombrar el directorio",
+       "failedToSaveTmpFile"          => "fallo al guardar el archivo temporal \"%1\" a nueva ubicación \"%2\"",
+       "fileAlreadyExists"            => "ya existe un archivo con ese nombre",
+       "filesCopied"                  => "%1 archivos copiados",
+       "illegalDirectoryName"         => "\"%1\" es un nombre de directorio inválido",
+       "illegalFileName"              => "\"%1\" es un nombre de archivo inválido",
+       "illegalTargetDirectory"       => "directorio destino inválido \"%1\"",
+       "isNotWritable"                => "\"%1\" no es editable",
+       "missingFileInSelection"       => "archivo faltante en la selección",
+       "noDataForFileID"              => "no hay datos para el archivo id \"%1\"",
+       "noDataForDirectoryID"         => "no hay datos para el directory id \"%1\"",
+       "noNativeZipCommand"           => "no hay comando \"zip\" en el servidor",
+       "permissionDeniedUpload"       => "permiso denegado para cargar archivos a este directorio",
+       "permissionDeniedCreateDirectory"=>"permiso denegado: no de puede crear el directorio",
+       "permissionDeniedCreateFile"   => "permiso denegado: no se puede crear el archivo",
+       "permissionDeniedDeleteDirectory"=>"permiso denegado: no se puede eliminar el directorio",
+       "permissionDeniedDeleteFile"   => "permiso denegado: no se puede eliminar el archivo",
+       "permissionDeniedEditDirectory"=> "permiso denegado: no se puede modificar el directorio",
+       "permissionDeniedEditFile"     => "permiso denegado: no se puede modificar el archivo",
+       "permissionDeniedMoveDirectory"=> "permiso denegado: no se puede mover el directorio",
+       "permissionDeniedMoveFile"     => "permiso denegado: no se puede mover el archivo",
+       "permissionDeniedRename"       => "permiso denegado: no se puede renombrar \"%1\"",
+       "permissionDeniedViewFile"     => "permiso denegado: no se puede ver el archivo",
+       "searchResults"                => "resultados de la búsqueda",
+       # 1.2
+       "fileNotCreatedDirUnwritable"    => "\"%1\" could not be created. The directory is not writable",
+       "fileNotDeletedUnwritable"       => "\"%1\" cannot be removed. (file not writable)",
+       "fileNotMovableUnwritable"       => "\"%1\" cannot be moved. (file not writable)",
+       "permissionDeniedManipImage"     => "permission denied: cannot manipulate images",
+       "imageNotWritable"               => "image is not writable",
+       "failedGetFileObject"            => "failed to retrieve File object",
+       "failedGetDirectoryObject"       => "failed to retrieve Directory object",
+       "failedDeleteFile"               => "failed to delete file \"%1\"",
+       "failedMoveFile"                 => "failed to move file \"%1\"",
+       "failedWriteToFile"              => "failed write to file \"%1\"",
+       "failedDownloadFromUrl"        => "failed to download from URL \"%1\""
+       ,
+       "file saved"                     => "file saved",
+       "files deleted"                  => "%1 files deleted",
+       "errorZipContainsBannedFilename" => "error: zip contains a banned filename",
+       "error: filename not allowed"    => "error: filename not allowed",
+       "error: url must begin with http"=> "error: url must begin with http",
+       "UNKNOWN TAG"                    => "UNKNOWN TAG \"%1\"",
+       "error: unzip failed"            => "error: unzip failed"
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/fa.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/fa.js
new file mode 100644 (file)
index 0000000..9390876
--- /dev/null
@@ -0,0 +1,152 @@
+/*\r
+ * See ../license.txt for licensing\r
+ *\r
+ * For further information visit:\r
+ *     http                    ://kfm.verens.com/\r
+ *\r
+ * File Name: fa.js\r
+ *     Persian language file.\r
+ *\r
+ * File Authors:\r
+ * Ghassem Tofighi http://ght.ir\r
+ * [MyFamily]@gmail.com\r
+ */\r
+\r
+kfm.lang={\r
+       AddTagsToFiles          : "افزودن تگ به این فایل(ها)",//add tags to file(s)\r
+       AllFiles                : "همه فایل‌ها",//all files\r
+       AllowedFileExtensions   : "پسوندهای مجاز برای فایل",//allowed file extensions\r
+       AndNMore                : "...و %1 بیشتر...",//...and %1 more...\r
+       AreYouSureYouWantToCloseKFM: "مطمئن هستید که می‌خواهید پنجره KFM را ببندبد؟",//Are you sure you want to close the KFM window?\r
+       AskIfOverwrite          : "فایل \"%1\" هم‌اکنون وجود دارد. بازنویسی شود؟",//The file \"%1\" already exists. Overwrite?\r
+       Browse                  : "گشتن...",//Browse...\r
+       Cancel                  : "لغو",//cancel\r
+       CouldNotWriteFile       : "خطا: فایل \"%1\ ذخیره نشد.",//error: could not write file \"%1\".\r
+       CreateSubDir            : "ساختن پوشه فرزند",//create sub-directory\r
+       CurrentWorkingDir       : "پوشه فعال جاری : \"%1\"",//Current Working Directory: \"%1\"\r
+       CouldNotRemoveDir       : "نمی‌توان پوشه را حذف کرد.\nلطفا ازخالی بودن آن مطمئن شوید",//cannot remove directory.\nplease make sure it is empty\r
+       CouldNotDownloadFile    : "خطا: نمی‌توان فایل \"%1\ را بارگذاری کرد.",//error: could not download file \"%1\".\r
+       CouldntReadDir          : "خطا: نمی‌توان پوشه را خواند",//error: couldn't read directory\r
+       CreateEmptyFile         : "ساختن فایل خالی",//create empty file\r
+       CloseWithoutSavingQuestion: "مطمئن هستید که می‌خواهید بدون ذخیره پنجره را ببندید؟",//Are you sure you want to close without saving?\r
+       CloseWithoutSaving      : "بستن بدون ذخیره",//Close Without Saving\r
+       CannotRenameFile        : "خطا: نمی‌توان از \"%1\" به \"%2\ تغییرنام داد",//error: cannot rename \"%1\" to \"%2\"\r
+       ChangeCaption           : "تغییر عنوان",//change caption\r
+       CreateDirMessage        : "ساختن یک پوشه فرزند برای \"%1\":",//Create a sub-directory of \"%1\":\r
+       CurrentSize             : "اندازه کنونی: \"%1\" x \"%2\"\n",//Current Size: \"%1\" x \"%2\"\n\r
+       ChangeCaption           : "تغییر عنوان",//Change Caption\r
+       Close                   : "بستن",//close\r
+       Caption                 : "عنوان",//caption\r
+       CommaSeparated          : "جدا کردن با کاما",//comma-separated\r
+       CopyFromURL             : "بارگذاری با URL",//Copy from URL\r
+       Dir                     : "rtl",//ltr // language direction\r
+       Directories             : "پوشه ها",//Directories\r
+       DeleteFile              : "حذف",//delete\r
+       DirEmpty                : "هیچ فایلی در \"%1\" وجود ندارد",//no files found in \"%1\"\r
+       DeleteDir               : "حذف",//delete\r
+       DelDirMessage           : "مطمئن هستید که می‌خواهید پوشه \"%1\" را حذف کنید؟",//Are you sure you want to delete the directory \"%1\"?\r
+       DelFileMessage          : "مطمئن هستید که می‌خواهید فایل \"%1\ را حذف کنید؟",//Are you sure you want to delete the file \"%1\"\r
+       DelMultipleFilesMessage : "مطمئن هستید که می‌خواهید فایل‌های زیر را حذف کنید؟\n\n",//Are you sure you want to delete the following files?\n\n\r
+       DownloadFileFromMessage : "بارگذاری فایل از کجا؟",//Download file from where?\r
+       DirRefreshed            : "پوشه‌ها تازه‌سازی شدند",//directories refreshed.\r
+       DirectoryNameExists     : "در حال حاضر یک پوشه با آن نام وجود دارد.",//a directory of that name already exists.\r
+       DownloadFileFromUrl     : "بارگیری فایل از یک URL",//download file from URL\r
+       DirectoryProperties     : "ویژگی‌های پوشه",//Directory Properties\r
+       DirNotInDb              : "پوشه در پایگاه داده نیست",//directory not in database\r
+       ErrorPrefix             : "خطا:",//error:\r
+       EditTextFile            : "ویرایش فایل متنی",//edit text file\r
+       ExtractAfterUpload      : "استخراج فایل‌ها پس از بارگیری",//extract after upload\r
+       ExtractZippedFile       : "استخراج فایل‌های فشرده",//Extract zipped file\r
+       FileSavedAsMessage      : "به چه نامی فایل ذخیره شود؟",//What should the file be saved as?\r
+       FileUpload              : "بارگیری فایل",//File Upload\r
+       FilesRefreshed          : "فایل‌ها تازه‌سازی شد.",//files refreshed.\r
+       FileSelected            : "فایل انتخاب‌شده: \"%1\"",//file selected: \"%1\"\r
+       FileNameNotAllowd       : "خطا: نام غیرمجاز برای فایل",//error: filename not allowed\r
+       FileTooLargeForThumb    : "خطا: \"%1\" برای ساختن تصویر بندانگشتی بسیار بزرگ است.لطفا فایل کوچکتری را جایگزین کنید.",//error: \"%1\" is too large to make a thumbnail. Please replace the file with a smaller version.\r
+       FilenameAlreadyExists   : "خطا: در حال حاضر یک فایل با آن نام وجود دارد",//error: a file of that name already exists\r
+       FileDetails             : "جزییات فایل",//File Details\r
+       Filename                : "نام فایل",//filename\r
+       Filesize                : "اندازه فایل",//filesize\r
+       HowWouldYouLikeToRenameTheseFiles: "چگونه می‌خواهید این فایل‌ها را تغییر نام دهید؟\n\n مثال:\"images-***.jpg\" به \"images-001.jpg\"، \"images-002.jpg\", ... تغییر نام پیدا خواهند کرد.",//How would you like to rename these files?\n\nexample: \"images-***.jpg\" will rename files to \"images-001.jpg\", \"images-002.jpg\", ...\r
+       InvertSelection         : "معکوس کردن انتخاب",//invert selection\r
+       IfYouUseMultipleWildcards: "اگر چند wildcard در قالب نام فایل استفاده می‌کنید، باید آنها را در یک گروه قرار دهید",//If you use multiple wildcards in the filename template, they must be grouped together\r
+       IllegalDirectoryName    : "\"%1\" نام غیر مجازی برای پوشه است",//illegal directory name \"%1\"\r
+       LockPanels              : "قفل‌کردن پنل‌ها",//lock panels\r
+       Loading                 : "بارگیری",//loading\r
+       LoadingKFM              : "بارگیری KFM",//loading KFM\r
+       Log_ChangeCaption: "تغییر عنوان از \"%1\" به \"%1\"",//changing caption of \"%1\" to \"%2\"\r
+       Logs                    : "رویدادنگاری‌ها",//Logs\r
+       MovingFilesTo           : "انتقال فایل‌های [\"%1\"] به \"%2\"",//moving files [\"%1\"] to \"%2\"\r
+       Maximise                : "بزرگ کردن",//maximise\r
+       Minimise                : "کوچک کردن",//minimise\r
+       MoveDown                : "انتقال به پایین",//move down\r
+       Mimetype                : "نوع mime",//mimetype\r
+       MoveUp                  : "انتقال به بالا",//move up\r
+       NewCaptionIsThisCorrect : "عنوان جدید:\n%1\n\nآیا درست است؟",//New Caption:\n%1\n\nIs this correct?\r
+       Name                    : "نام",//name\r
+       NewDirectory            : "پوشه جدید",//New Directory\r
+       NoRestrictions          : "بدون محدودیت",//no restrictions\r
+       NoForwardslash          : "\nنمی‌توان از '/' در نام فایل استفاده کرد",//\nYou may not use '/' in the filename\r
+       NewWidth                : "عرض جدید؟",//New Width?\r
+       NoPanel                 : "خطا:پنل \"%1\" وجود ندارد.",//error: panel \"%1\" doesn\'t exist.\r
+       NotAnImageOrImageDimensionsNotReported: "خطا: یک عکس نیست یا ابعاد تصویر گزارش نشده است",//error: not an image, or image dimensions not reported\r
+       NewCaption              : "عنوان جدید؟",//New Caption\r
+       NewWidthConfirmTxt      : "عرض جدید: \"%1\"\n",//New Width: \"%1\"\n\r
+       NewHeight               : "ارتفاع جدید؟",//New Height?\r
+       NewHeightConfirmTxt     : "ارتفاع جدید:\"%1\"\n\n درست است؟",//New Height: \"%1\"\n\nIs this correct?\r
+       NotMoreThanOneFile      : "خطا: شما نمی‌توانید بیش از یک فایل در آن واحد انتخاب کنید",//error: you cannot choose more than one file at a time\r
+       NoFilesSelected         : "هیچ فایلی انتخاب نشده است",//no files selected\r
+       PermissionDeniedCannotDeleteFile: "خطای مجوز: نمی‌توان فایل را حذف کرد",//permission denied: cannot delete file\r
+       PleaseSelectFileBeforeRename: "لطفا قبل از تغییر نام دادن، یک فایل انتخاب کنید",//Please select a file before you try to rename it\r
+       RenameDir               : "تغییر نام",//rename\r
+       RenameFile              : "تغییر نام",//rename\r
+       RotateClockwise         : "چرخش ساعتگرد",//rotate clock-wise\r
+       RotateAntiClockwise     : "چرخش پادساعتگرد",//rotate anti-clockwise\r
+       ResizeImage             : "تغییر اندازه تصویر",//resize image\r
+       RenamedFile             : "تغییر نام فایل از \"%1\" به \"%2\.",//renaming file \"%1\" to \"%2\".\r
+       Restore                 : "واگردانی",//restore\r
+       ReturnThumbnailToOpener : "بازگرداندن تصویر بندانگشتی به ویرایشگر",//return thumbnail to editor\r
+       RenameOnlyOneFile       : "شما تنها می‌توانید نام یک فایل را در هر لحظه عوض کنید",//You can only rename one file at a time\r
+       RecursiveDeleteWarning  : "\"%1\" خالی نیست\n آیا مطمئن هستید که مایلبه حذف آن و تمام محتویاتش هستید؟\n*هشدار*: این کار برگشت‌پذیر نیست",//\"%1\" is not empty\nAre you sure you want to delete it and all its contents?\n*WARNING* THIS IS NOT REVERSIBLE\r
+       RmdirFailed             : "تلاش برای حذف پوشه \"%1\ بی‌نتیجه ماند",//failed to delete directory \"%1\"\r
+       RenamedDirectoryAs      : "تغییر نام از '%1' به '%2'",//Renamed '%1' as '%2'\r
+       RenameFileToWhat        : "تغییر نام فایل \"%1\" به چه نامی؟",//Rename the file \"%1\" to what?\r
+       RenameTheDirectoryToWhat: "تغییر نام پوشه \"%1\" به چه نامی؟",//Rename the directory '%1' to what?\r
+       RemoveTagsFromFiles     : "برداشتن تگ‌ها از فایل‌ها",//remove tags from file(s)\r
+       SetStylesError          : "خطا: نمی‌توان \"%1\" را به \"%2\ تنظیم کرد.",//error: cannot set \"%1\" to \"%2\.\r
+       SaveThenClose           : "ذخیره، سپس بستن",//Save, then Close\r
+       SaveThenCloseQuestion   : "آیا مطمئن هستید که میخواهید تغییرات داده شده را ذخیره نمایید؟",//Are you sure you want to save the changes you made?\r
+       SelectAll               : "انتخاب همه",//select all\r
+       SelectNone              : "انتخاب هیچکدام",//select none\r
+       Search                  : "جستجو",//Search\r
+       ShowPanel               : "نمایش پنل \"%1\"",//show panel \"%1\"\r
+       Tags                    : "تگ‌ها",//tags\r
+       TheFilenameShouldEndWithN: "نام فایل باید با %1 تمام شود",//The filename should end with %1\r
+       UnknownPanelState       : "خطا:وضعیت نامشخص پنل.",//error: unknown panel state.\r
+       UrlNotValidLog          : "خطا: URL باید با \"http:\" شروع شود",//error: URL must begin with \"http:\"\r
+       UnlockPanels            : "گشودن قفل پنل‌ها",//unlock panels\r
+       UrlNotValid             : "خطا: URL باید با \"http:\" شروع شود",//error: URL must begin with \"http:\"\r
+       Upload                  : "بارگیری",//Upload\r
+       ViewImage               : "مشاهده تصویر",//view image\r
+       WhatFilenameDoYouWantToUse: "چه نام فایلی می‌خواهید استفاده کنید؟",//What filename do you want to use?\r
+       WhatFilenameToCreateAs  : "به چه عنوانی فایل ساخته شود؟",//What should the file be created as?\r
+       WhatMaximumSize         : "چه مقدار بیشینه‌ای باید بازگردانده شود؟",//What maximum size should be returned?\r
+       WhatIsTheNewTag         : "تگ جدید چیست؟\nبرای چند تگ، آنها را با کاما جدا کنید.",//What is the new tag?\nFor multiple tags, separate by commas.\r
+       WhichTagsDoYouWantToRemove: "چه تگ‌هایی را می‌خواهید حذف کنید؟\n برای چند تگ آنها را با کاما جدا کنید.",//Which tags do you want to remove?\nFor multiple tags, separate by commas.\r
+       YouMustPlaceTheWildcard : "شما باید کاراکتر wildcard * را جایی در قالب نام فایل قرار دهید",//You must place the wildcard character * somewhere in the filename template\r
+       YouNeedMoreThan         : "شما بیشتر از %1 * کاراکتر برای ساختن نام فایل %2 نیاز دارید",//You need more than %1 * characters to create %2 filenames\r
+       ZipUpFiles              : "فشرده‌سازی همه فایل‌ها"//zip up files\r
+       , // new in 1.2\r
+       Icons                   : "آیکن‌ها",//icons// used to select mode of file view\r
+       ListView                : "نمایش لیست",//list-view // used to select mode of file view\r
+       SendToCms               : "ارسال به CMS",//send to CMS // close KFM and return the selected files to the CMS\r
+       CannotMoveDirectory     : "خطای مجوز: نمی‌توان پوشه را منتقل کرد",//permission denied: cannot move directory\r
+       LastModified            : "آخرین ویرایش",//last modified // part of File Details\r
+       ImageDimensions         : "ابعاد تصویر", //image dimensions// part of File Details\r
+       CouldNotMoveFiles       : "خطا:نمی‌توان فایل(ها) را منتقل کرد",//error: could not move file[s]\r
+       CopyFiles               : "کپی فایل‌ها",//copy files // when dragging files to a directory, two choices appear - "copy files" and "move files"\r
+       MoveFiles               : "انتقال فایل‌ها",//move files\r
+       AboutKfm                : "درباره KFM",//about KFM\r
+       Errors                  : "خطاها",//Errors\r
+       Ok                      : "تایید"//OK // as in "OK / Cancel"\r
+}\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/fa.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/fa.php
new file mode 100644 (file)
index 0000000..918216e
--- /dev/null
@@ -0,0 +1,74 @@
+<?php\r
+/*\r
+ * See ../license.txt for licensing\r
+ *\r
+ * For further information visit:\r
+ *  http://kfm.verens.com/\r
+ *\r
+ * File Name: fa.php\r
+ *  Persian language file.\r
+ *\r
+ * File Authors:\r
+ * Ghassem Tofighi http://ght.ir\r
+ * [MyFamily]@gmail.com\r
+ */\r
+\r
+$kfm_langStrings=array(\r
+       "alreadyExists"                  => "\"%1\" وجود دارد",//\"%1\" already exists\r
+       "errorInvalidID"                 => "خطا: شماره نامعنبر",//error: invalid ID\r
+       "errorFileIDNotFound"            => "خطا: فایل با شماره #%1 در پایگاه داده پیدا نشد.",//error: file id #%1 not found in database\r
+       "bannedFilenameExtension"        => "پسوند ممنوع در نام فایل",//banned extension in file name\r
+       "cannotEditRestrictedExtension"  => "نمی‌توان \"%1\" را ویرایش کرد\nمحدود شده با پسوند",//cannot edit \"%1\"\nrestricted by file extension\r
+       "cannotMoveIntoSelf"             => "نمی‌توان یک پوشه را به پشه فرزندش منتقل کرد",//cannot move a directory into its own sub-directory\r
+       "cannotRenameFromTo"             => "نمی‌توان \"%1\" را به \"%2\" تغییر نام داد",//cannot rename \"%1\" to \"%2\"\r
+       "CMSRefusesFileDelete"           => "CMS اجازه حذف \"%1\" را نمی‌دهد",//CMS does not allow \"%1\" to be deleted\r
+       "couldNotMoveDirectory"          => "نمی‌توان پوشه \"%1\" را به \"%2\" منتقل کرد",//could not move directory \"%1\" to \"%2\"\r
+       "couldNotCreateFile"             => "فایل \"%1\" نوشته نشد",//could not write file \"%1\"\r
+       "errorSettingFileContent"        => "خطا در تنظیم محتوای فایل",//error setting file content\r
+       "failedCreateDirectoryCheck"     => "ایجاد پوشه \"%1\" بی‌نتیجه ماند\nمجوز سیستم فایل را بررسی کنید",//failed to create directory \"%1\"\ncheck filesystem permissions\r
+       "failedRenameDirectory"          => "تغییر نام پوشه بی‌نتیجه ماند",//failed to rename directory\r
+       "failedToSaveTmpFile"            => "عدم موفقیت در ذخیره فایل موقت \"%1\" در محل \"%2\"",//failure to save tmp file \"%1\" to location \"%2\"\r
+       "fileAlreadyExists"              => "یک فایل با همان نام وجود دارد",//a file of that name already exists\r
+       "filesCopied"                    => "%1 فایل کپی شد",//%1 files copied\r
+       "illegalDirectoryName"           => "\"%1\" یک نام غیر مجاز برای پوشه است",//\"%1\" is an illegal directory name\r
+       "illegalFileName"                => "\"%1\" یک نام غیرمجاز برای نام فایل است",//\"%1\" is an illegal file name\r
+       "illegalTargetDirectory"         => "پوشه مقصد \"%1\" غیرمجاز است",//illegal target directory \"%1\"\r
+       "isNotWritable"                  => "\"%1\" قابل نوشتن نیست",//\"%1\" is not writable\r
+       "missingFileInSelection"         => "فایل از قلم‌افتاده در انتخاب",//missing file in selection\r
+       "noDataForFileID"                => "هیچ داده‌ای برای شماره فایل \"%1\" موجود نیست",//no data for file id \"%1\"\r
+       "noDataForDirectoryID"           => "هیچ داده‌ای برای شماره پوشه \"%1\" موجود نیست",//no data for directory id \"%1\"\r
+       "noNativeZipCommand"             => "دستور \"zip\" در سرور پیدا نشد",//no \"zip\" command found on server\r
+       "permissionDeniedUpload"         => "خطای مجوز برای بارگیری در این پوشه",//permission denied for upload to this directory\r
+       "permissionDeniedCreateDirectory"=> "خطای مجوز: نمی‌توان پوشه را ساخت",//permission denied: cannot create directory\r
+       "permissionDeniedCreateFile"     => "خطای مجوز: نمی‌توان فایل را ایجاد کرد",//permission denied: cannot create file\r
+       "permissionDeniedDeleteDirectory"=> "خطای مجوز: نمی‌توان پوشه را حذف کرد",//permission denied: cannot delete directory\r
+       "permissionDeniedDeleteFile"     => "خطای مجوز: نمی‌توان فایل را حذف کرد",//permission denied: cannot delete file\r
+       "permissionDeniedEditDirectory"  => "خطای مجوز: نمی‌توان پوشه را ویرایش کرد",//permission denied: cannot edit directory\r
+       "permissionDeniedEditFile"       => "خطای مجوز: نمی‌توان فایل را ویرایش کرد",//permission denied: cannot edit file\r
+       "permissionDeniedMoveDirectory"  => "خطای مجوز: نمی‌توان پوشه را منتقل کرد",//permission denied: cannot move directory\r
+       "permissionDeniedMoveFile"       => "خطای مجوز: نمی‌توان فایل را منتقل کرد",//permission denied: cannot move file\r
+       "permissionDeniedRename"         => "خطای مجوز: نمی‌توان \"%1\" را تغییر نام داد",//permission denied: cannot rename \"%1\"\r
+       "permissionDeniedViewFile"       => "خطای مجوز: نمی‌توان فایل را مشاهده کرد",//permission denied: cannot view file\r
+       "searchResults"                  => "نتایج جستجو",//search results\r
+       # 1.2\r
+       "fileNotCreatedDirUnwritable"    => "خطا: \"%1\" ساخته نشد. پوشه قابل نوشتن نیست",//error: \"%1\" could not be created. The directory is not writable\r
+       "fileNotDeletedUnwritable"       => "خطا: نمی‌توان \"%1\" را حذف کرد. (فایل قابل نوشتن نیست)",//error: \"%1\" cannot be removed. (file not writable)\r
+       "fileNotMovableUnwritable"       => "خطا: نمی‌توان \"%1\" را منتقل کرد. (فایل قابل نوشتن نیست)",//error: \"%1\" cannot be moved. (file not writable)\r
+       "permissionDeniedManipImage"     => "خطا: خطای مجوز: نمی‌توان تصاویر را دستکاری کرد",//error: permission denied: cannot manipulate images\r
+       "imageNotWritable"               => "خطا: تصویر قابل ویرایش نیست",//error: image is not writable\r
+       "failedGetFileObject"            => "خطا: بازیابی فایل بی‌نتیجه ماند",//error: failed to retrieve File object\r
+       "failedGetDirectoryObject"       => "خطا: بازیابی پوشه بی‌نتیجه ماند",//error: failed to retrieve Directory object\r
+       "failedDeleteFile"               => "خطا: حذف فایل \"%1\" بی‌نتیجه ماند",//error: failed to delete file \"%1\"\r
+       "failedMoveFile"                 => "خطا: انتقال فایل \"%1\" بی‌نتیجه ماند",//error: failed to move file \"%1\"\r
+       "failedWriteToFile"              => "خطا: نوشتن در فایل \"%1\" بی‌نتیجه ماند",//error: failed write to file \"%1\"\r
+       "failedDownloadFromUrl"          => "خطا: بارگذاری از URL \"%1\" بی‌نتیجه ماند"//error: failed to download from URL \"%1\"\r
+       ,\r
+       "file saved"                     => "فایل ذخیره شد",//file saved\r
+       "files deleted"                  => "فایل‌های %1 حذف شدند",//%1 files deleted\r
+       "errorZipContainsBannedFilename" => "خطا: فایل zip شامل نام فایل‌های غیرمجاز است",//error: zip contains a banned filename\r
+       "error: filename not allowed"    => "خطا: نام فایل غیرمجاز است",//error: filename not allowed\r
+       "error: url must begin with http"=> "خطا: url باید با http شروع شود",//error: url must begin with http\r
+       "UNKNOWN TAG"                    => "تگ نامشخص \"%1\"",//UNKNOWN TAG \r
+       "error: unzip failed"            => "خطا: استخراج فایل‌ها بی‌نتیجه ماند"//error: unzip failed\r
+);\r
+?>\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/fi.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/fi.js
new file mode 100644 (file)
index 0000000..e2d79d7
--- /dev/null
@@ -0,0 +1,293 @@
+/*\r
+ * See ../license.txt for licensing\r
+ *\r
+ * For further information visit:\r
+ *     http://kfm.verens.com/\r
+ *\r
+ * File Name: fi.js\r
+ *     Finnish language file.\r
+ *\r
+ * File Authors:\r
+ *     hnpilot@phnet.fi\r
+ */\r
+\r
+kfm.lang=\r
+{\r
+Dir:\r
+       "ltr", // language direction\r
+ErrorPrefix:\r
+       "virhe: ",\r
+// what you see on the main page\r
+Directories:\r
+       "Hakemistot",\r
+CurrentWorkingDir:\r
+       "Nykyinen hakemisto: \"%1\"",\r
+Logs:\r
+       "Lokit",\r
+FileUpload:\r
+       "Tiedoston lisäys",\r
+DirEmpty:\r
+       "ei tiedostoja hakemistossa \"%1\"",\r
+\r
+// right click menu item directory\r
+// directory\r
+CreateSubDir:\r
+       "luo alihakemisto",\r
+DeleteDir:\r
+       "poista",\r
+RenameDir:\r
+       "nimeä uudelleen",\r
+\r
+// file\r
+DeleteFile:\r
+       "poista",\r
+RenameFile:\r
+       "nimeä uudelleen",\r
+RotateClockwise:\r
+       "kierrä myötäpäivään",\r
+RotateAntiClockwise:\r
+       "kierrä vastapäivään",\r
+ResizeImage:\r
+       "muuta kuvan kokoa",\r
+ChangeCaption:\r
+       "vaihda otsikkoa",\r
+\r
+// create a file\r
+WhatFilenameToCreateAs:\r
+       "Minkä niminen tiedosto luodaan?",\r
+AskIfOverwrite:\r
+       "Tiedosto \"%1\" on jo olemassa. Kirjoitetaanko päälle?",\r
+NoForwardslash:\r
+       "\nEt voi käyttää '/' tiedostonimessä",\r
+\r
+// messages management\r
+CreateDirMessage:\r
+       "Luo alihakemisto hakemistolle \"%1\":",\r
+DelDirMessage:\r
+       "Haluatko varmasti poistaa hakemiston \"%1\"?",\r
+DelFileMessage:\r
+       "Haluatko varmasti poistaa tiedoston \"%1\"",\r
+DelMultipleFilesMessage:\r
+       "Haluatko varmasti poistaa seuraavat tiedostot?\n\n'",\r
+DownloadFileFromMessage:\r
+       "Lataa tiedosto mistä?",\r
+FileSavedAsMessage:\r
+       "Millä nimellä tiedosto tallennetaan?",\r
+\r
+// resize file\r
+CurrentSize:\r
+       "Nykyinen koko: \"%1\" x \"%2\"\n",\r
+NewWidth:\r
+       "Uusi leveys?",\r
+NewWidthConfirmTxt:\r
+       "Uusi leveys: \"%1\"\n",\r
+NewHeight:\r
+       "Uusi korkeus?",\r
+NewHeightConfirmTxt:\r
+       "Uusi korkeus: \"%1\"\n\nOnko tämä oikein?",\r
+\r
+// log messages\r
+RenamedFile:\r
+       "uudelleennimetään tiedosto \"%1\" tiedostoksi \"%2\".",\r
+DirRefreshed:\r
+       "hakemistot päivitetty.",\r
+FilesRefreshed:\r
+       "tiedostot päivitetty.",\r
+NotMoreThanOneFile:\r
+       "virhe: et voi valita kuin yhden tiedoston kerrallaan",\r
+UnknownPanelState:\r
+       "virhe: tuntematon tila.",\r
+// MissingDirWrapper:\r
+//     "error: puuttuva tiedoston wrapperi: \"kfm_directories%1\".",\r
+SetStylesError:\r
+       "virhe:  \"%1\" ei voi asettaa \"%2\:ksi.",\r
+NoPanel:\r
+       "virhe: panelia \"%1\" ei ole.",\r
+FileSelected:\r
+       "Valittu tiedosto: \"%1\"",\r
+Log_ChangeCaption:\r
+       "muutetaan otsikko \"%1\" otsikoksi \"%2\"",\r
+UrlNotValidLog:\r
+       "virhe: URL:n täytyy alkaa \"http:\"",\r
+MovingFilesTo:\r
+       "siirretään tiedostot [\"%1\"] hakemistoon \"%2\"",\r
+\r
+// error messages\r
+DirectoryNameExists:\r
+       "nimetty tiedosto on jo olemassa.",\r
+FileNameNotAllowd:\r
+       "virhe: tiedostonimi ei ole sallittu",\r
+CouldNotWriteFile:\r
+       "virhe: ei voinut kirjoittaa tiedostoon \"%1\".",\r
+CouldNotRemoveDir:\r
+       "ei voinut poistaa hekmistoa.\nvarmista, että se on tyhjä",\r
+UrlNotValid:\r
+       "virhe: URL:n täytyy alkaaa \"http:\"",\r
+CouldNotDownloadFile:\r
+       "virhe: ei voinut ladata tiedostoa \"%1\".",\r
+FileTooLargeForThumb:\r
+       "virhe: \"%1\" on liian iso pikkukuvan tekemiseksi. Korvaa kuva pienemmällä tiedostolla.",\r
+CouldntReadDir:\r
+       "virhe: ei voinut lukea hakemistoa",\r
+CannotRenameFile:\r
+       "virhe: ei voi nimetä \"%1\" nimelle \"%2\"",\r
+FilenameAlreadyExists:\r
+       "virhe: nimetty tiedosto on jo olemassa",\r
+\r
+// new in 0.5\r
+EditTextFile:\r
+       "muokkaa tekstitiedostoa",\r
+CloseWithoutSavingQuestion:\r
+       "Oletko varma, ettähaluat sulkea tallentamatta?",\r
+CloseWithoutSaving:\r
+       "Sulje tallentamatta",\r
+SaveThenClose:\r
+       "Tallenna ja sulje",\r
+SaveThenCloseQuestion:\r
+       "Oletko varma, että haluat tallentaa muutoksesi?",\r
+\r
+// new in 0.6\r
+LockPanels:\r
+       "Lukitse panelit",\r
+UnlockPanels:\r
+       "poista panelien lukko",\r
+CreateEmptyFile:\r
+       "luo tyhjä tiedosto",\r
+DownloadFileFromUrl:\r
+       "lataa tiedosto URL:stä",\r
+DirectoryProperties:\r
+       "Hakemiston ominaisuudet",\r
+SelectAll:\r
+       "valitse kaikki",\r
+SelectNone:\r
+       "poista valinta",\r
+InvertSelection:\r
+       "käännä valinta",\r
+LoadingKFM:\r
+       "lataamassa KFM:ää",\r
+Name:\r
+       "nimi",\r
+FileDetails:\r
+       "Tiedoston tiedot",\r
+Search:\r
+       "Etsi",\r
+IllegalDirectoryName:\r
+       "laiton hakemistonimi \"%1\"",\r
+RecursiveDeleteWarning:\r
+       "\"%1\" ei ole tyhjä\nOletko varma, että haluat poistaa sen ja kaikki sen sisältämät tiedostot?\n*VAROITUS* TÄTÄ EI VOI PERUA!",\r
+RmdirFailed:\r
+       "hakemiston poisto epäonnistui \"%1\"",\r
+DirNotInDb:\r
+       "hakemistoa ei ole tietokannassa",\r
+ShowPanel:\r
+       "näytä paneli \"%1\"",\r
+ChangeCaption:\r
+       "Vaihda otsikkoa",\r
+NewDirectory:\r
+       "Uusi hakemisto",\r
+Upload:\r
+       "Lähetä tiedosto",\r
+NewCaptionIsThisCorrect:\r
+       "Uusi otsikko:\n%1\n\nOnko tämä oikein?",\r
+Close:\r
+       "sulje",\r
+Loading:\r
+       "lataamssa",\r
+AreYouSureYouWantToCloseKFM:\r
+       "Haluatko varmasti sulkea KFM-ikkunan?",\r
+PleaseSelectFileBeforeRename:\r
+       "Valitse ensin tiedosto",\r
+RenameOnlyOneFile:\r
+       "Voit uudelleennimetä vain yhden tiedoston kerrallaan",\r
+RenameFileToWhat:\r
+       "vaihda nimi \"%1\" miksi?",\r
+NoRestrictions:\r
+       "ei rajoituksia",\r
+Filename:\r
+       "tiedoston nimi",\r
+Maximise:\r
+       "suurenna",\r
+Minimise:\r
+       "pienennä",\r
+AllowedFileExtensions:\r
+       "sallitut tiedostopäätteet",\r
+Filesize:\r
+       "koko",\r
+MoveDown:\r
+       "siirrä alas",\r
+Mimetype:\r
+       "MIME-tyyppi",\r
+MoveUp:\r
+       "siirrä ylös",\r
+Restore:\r
+       "palauta",\r
+Caption:\r
+       "otsikko",\r
+CopyFromURL:\r
+       "Copy from URL",\r
+ExtractZippedFile:\r
+       "Extract zipped file",\r
+\r
+// new in 0.8\r
+ViewImage:\r
+       "view image",\r
+ReturnThumbnailToOpener:\r
+       "return thumbnail to opener",\r
+AddTagsToFiles:\r
+       "add tags to file(s)",\r
+RemoveTagsFromFiles:\r
+       "remove tags from file(s)",\r
+HowWouldYouLikeToRenameTheseFiles:\r
+       "How would you like to rename these files?\n\nexample: \"images-***.jpg\" will rename files to \"images-001.jpg\", \"images-002.jpg\", ...",\r
+YouMustPlaceTheWildcard:\r
+       "You must place the wildcard character * somewhere in the filename template",\r
+YouNeedMoreThan:\r
+       "You need more than %1 * characters to create %2 filenames",\r
+NoFilesSelected:\r
+       "no files selected",\r
+Tags:\r
+       "tags",\r
+IfYouUseMultipleWildcards:\r
+       "If you use multiple wildcards in the filename template, they must be grouped together",\r
+NewCaption:\r
+       "New Caption",\r
+WhatMaximumSize:\r
+       "What maximum size should be returned?",\r
+CommaSeparated:\r
+       "comma-separated",\r
+WhatIsTheNewTag:\r
+       "What is the new tag?\nFor multiple tags, separate by commas.",\r
+WhichTagsDoYouWantToRemove:\r
+       "Which tags do you want to remove?\nFor multiple tags, separate by commas."\r
+\r
+,\r
+// New in 0.9\r
+AllFiles: "all files",\r
+AndNMore: "...and %1 more...",\r
+Browse: "Browse...",\r
+ExtractAfterUpload: "extract after upload",\r
+NotAnImageOrImageDimensionsNotReported: "error: not an image, or image dimensions not reported",\r
+PermissionDeniedCannotDeleteFile: "permission denied: cannot delete file",\r
+RenameTheDirectoryToWhat: "Rename the directory '%1' to what?",\r
+RenamedDirectoryAs: "Renamed '%1' as '%2'",\r
+TheFilenameShouldEndWithN: "The filename should end with %1",\r
+WhatFilenameDoYouWantToUse: "What filename do you want to use?"\r
+\r
+,\r
+// New in 1.0\r
+ZipUpFiles: "zip up files",\r
+Cancel: "cancel"\r
+       , // new in 1.2\r
+       Icons                   : "icons", // used to select mode of file view\r
+       ListView                : "list-view", // used to select mode of file view\r
+       SendToCms               : "send to CMS", // close KFM and return the selected files to the CMS\r
+       CannotMoveDirectory     : "permission denied: cannot move directory",\r
+       LastModified            : "last modified", // part of File Details\r
+       ImageDimensions         : "image dimensions", // part of File Details\r
+       CouldNotMoveFiles       : "error: could not move file[s]",\r
+       CopyFiles               : "copy files", // when dragging files to a directory, two choices appear - "copy files" and "move files"\r
+       MoveFiles               : "move files",\r
+       AboutKfm                : "about KFM",\r
+       Errors                  : "Errors",\r
+       Ok                      : "OK" // as in "OK / Cancel"\r
+}\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/fi.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/fi.php
new file mode 100644 (file)
index 0000000..55880b8
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *
+ * File Name: fi.php
+ *  Finnish language file.
+ *
+ * File Authors:
+ *  kae@verens.com
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                => "\"%1\" already exists",
+       "errorInvalidID"               => "error: invalid ID",
+       "errorFileIDNotFound"          => "error: file id #%1 not found in database",
+       "bannedFilenameExtension"      => "banned extension in file name",
+       "cannotEditRestrictedExtension"=> "cannot edit \"%1\"\nrestricted by file extension",
+       "cannotMoveIntoSelf"           => "cannot move a directory into its own sub-directory",
+       "cannotRenameFromTo"           => "cannot rename \"%1\" to \"%2\"",
+       "CMSRefusesFileDelete"         => "CMS does not allow \"%1\" to be deleted",
+       "couldNotMoveDirectory"        => "could not move directory \"%1\" to \"%2\"",
+       "couldNotCreateFile"           => "could not write file \"%1\"",
+       "errorSettingFileContent"      => "error setting file content",
+       "failedCreateDirectoryCheck"   => "failed to create directory \"%1\"\ncheck filesystem permissions",
+       "failedRenameDirectory"        => "failed to rename directory",
+       "failedToSaveTmpFile"          => "failure to save tmp file \"%1\" to location \"%2\"",
+       "fileAlreadyExists"            => "a file of that name already exists",
+       "filesCopied"                  => "%1 files copied",
+       "illegalDirectoryName"         => "\"%1\" is an illegal directory name",
+       "illegalFileName"              => "\"%1\" is an illegal file name",
+       "illegalTargetDirectory"       => "illegal target directory \"%1\"",
+       "isNotWritable"                => "\"%1\" is not writable",
+       "missingFileInSelection"       => "missing file in selection",
+       "noDataForFileID"              => "no data for file id \"%1\"",
+       "noDataForDirectoryID"         => "no data for directory id \"%1\"",
+       "noNativeZipCommand"           => "no \"zip\" command found on server",
+       "permissionDeniedUpload"       => "permission denied for upload to this directory",
+       "permissionDeniedCreateDirectory"=>"permission denied: cannot create directory",
+       "permissionDeniedCreateFile"   => "permission denied: cannot create file",
+       "permissionDeniedDeleteDirectory"=>"permission denied: cannot delete directory",
+       "permissionDeniedDeleteFile"   => "permission denied: cannot delete file",
+       "permissionDeniedEditDirectory"=> "permission denied: cannot edit directory",
+       "permissionDeniedEditFile"     => "permission denied: cannot edit file",
+       "permissionDeniedMoveDirectory"=> "permission denied: cannot move directory",
+       "permissionDeniedMoveFile"     => "permission denied: cannot move file",
+       "permissionDeniedRename"       => "permission denied: cannot rename \"%1\"",
+       "permissionDeniedViewFile"     => "permission denied: cannot view file",
+       "searchResults"                => "search results",
+       # 1.2
+       "fileNotCreatedDirUnwritable"    => "\"%1\" could not be created. The directory is not writable",
+       "fileNotDeletedUnwritable"       => "\"%1\" cannot be removed. (file not writable)",
+       "fileNotMovableUnwritable"       => "\"%1\" cannot be moved. (file not writable)",
+       "permissionDeniedManipImage"     => "permission denied: cannot manipulate images",
+       "imageNotWritable"               => "image is not writable",
+       "failedGetFileObject"            => "failed to retrieve File object",
+       "failedGetDirectoryObject"       => "failed to retrieve Directory object",
+       "failedDeleteFile"               => "failed to delete file \"%1\"",
+       "failedMoveFile"                 => "failed to move file \"%1\"",
+       "failedWriteToFile"              => "failed write to file \"%1\"",
+       "failedDownloadFromUrl"        => "failed to download from URL \"%1\""
+       ,
+       "file saved"                     => "file saved",
+       "files deleted"                  => "%1 files deleted",
+       "errorZipContainsBannedFilename" => "error: zip contains a banned filename",
+       "error: filename not allowed"    => "error: filename not allowed",
+       "error: url must begin with http"=> "error: url must begin with http",
+       "UNKNOWN TAG"                    => "UNKNOWN TAG \"%1\"",
+       "error: unzip failed"            => "error: unzip failed"
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/fr.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/fr.js
new file mode 100644 (file)
index 0000000..caf4d93
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * Licensed under the terms of the GNU Lesser General Public License:
+ * 
+       http:
+ *
+ * For further information visit:
+ * 
+       http:
+ *
+ * File Name: fr.js
+ * 
+       French language file.
+ *
+ * File Authors:
+ * 
+       liane
+ */
+
+kfm.lang=
+{
+Dir:
+       "ltr", 
+ErrorPrefix:
+       "erreur: ",
+
+Directories:
+       "Dossiers",
+CurrentWorkingDir:
+       'Dossier Actuel: "%1"',
+Logs:
+       "Messages",
+FileUpload:
+       "Envoi de fichier",
+DirEmpty:
+       'aucun fichier dans "%1"',
+
+CreateSubDir:
+       "nouveau sous-dossier",
+DeleteDir:
+       "supprimer",
+RenameDir:
+       "renommer",
+
+DeleteFile:
+       "supprimer",
+RenameFile:
+       "renommer",
+RotateClockwise:
+       "rotation sens horaire",
+RotateAntiClockwise:
+       "rotation sens anti-horaire",
+ResizeImage:
+       "redimensionner l'image",
+ChangeCaption:
+       "modifier le titre",
+
+WhatFilenameToCreateAs:
+       "Créer le fichier sous quel nom?",
+AskIfOverwrite:
+       'Le fichier "%1" existe déjà. Remplacer?',
+NoForwardslash:
+       "\nVous ne pouvez pas utiliser '/' dans le nom du fichier",
+
+CreateDirMessage:
+       'Créer un sous-dossier de "%1": ',
+DelDirMessage:
+       'Etes-vous certain de vouloir supprimer le dossier "%1"?',
+DelFileMessage:
+       'Etes-vous certain de vouloir supprimer le fichier "%1"?',
+DelMultipleFilesMessage:
+       "Etes-vous certain de vouloir supprimer les fichiers suivants?\n\n'",
+DownloadFileFromMessage:
+       "Télécharger le fichier de quel emplacement?",
+FileSavedAsMessage:
+       "Sous quel nom désirez-vous enregistrer le fichier?",
+
+CurrentSize:
+       'Taille Actuelle: "%1" x "%2"\n',
+NewWidth:
+       "Nouvelle Largeur?",
+NewWidthConfirmTxt:
+       'Nouvelle Largeur: "%1"\n',
+NewHeight:
+       "Nouvelle Hauteur?",
+NewHeightConfirmTxt:
+       'Nouvelle Hauteur: "%1"\n\nLes informations sont-elles exactes?',
+
+RenamedFile:
+       'fichier "%1" renommé en "%2".',
+DirRefreshed:
+       "dossiers actualisés.",
+FilesRefreshed:
+       "fichiers actualisés.",
+NotMoreThanOneFile:
+       "erreur: vous ne pouvez choisir qu'un fichier à la fois",
+UnknownPanelState:
+       "erreur: état du panneau inconnu.",
+MissingDirWrapper:
+       'erreur: dossier parent manquant: "kfm_directories%1".',
+SetStylesError:
+       'erreur: impossible d\'attribuer "%2" à "%1".',
+NoPanel:
+       'erreur: le panneau "%1" n\'existe pas.',
+FileSelected:
+       'fichier sélectionné: "%1"',
+Log_ChangeCaption:
+       'titre de "%1" modifié en "%2"',
+UrlNotValidLog:
+       'erreur: l\'URL doit commencer par "http:"',
+MovingFilesTo:
+       'fichiers ["%1"] déplacés dans "%2"',
+
+DirectoryNameExists:
+       "un dossier de ce nom existe déjà.",
+FileNameNotAllowd:
+       "erreur: nom de fichier incorrect",
+CouldNotWriteFile:
+       'erreur: impossible d\'écrire le fichier "%1".',
+CouldNotRemoveDir:
+       "Impossible de supprimer le dossier.\nAssurez-vous qu'il est vide",
+UrlNotValid:
+       'erreur: l\'URL doit commencer par "http:"',
+CouldNotDownloadFile:
+       'erreur: impossible de télécharger le fichier "%1".',
+FileTooLargeForThumb:
+       'erreur: "%1" est trop gros pour créer une vignette. Veuillez remplacer ce fichier par une version plus petite.',
+CouldntReadDir:
+       "erreur: impossible de lire ce dossier",
+CannotRenameFile:
+       'erreur: impossible de renommer "%1" en "%2"',
+FilenameAlreadyExists:
+       "erreur: un fichier de ce nom existe déjà",
+
+// new in 0.5
+EditTextFile:
+       "Editer fichier texte",
+CloseWithoutSavingQuestion:
+       "Etes-vous certain de vouloir fermer sans enregistrer?",
+CloseWithoutSaving:
+       "Fermer sans enregistrer",
+SaveThenClose:
+       "Enregistrer, puis fermer",
+SaveThenCloseQuestion:
+       "Etes-vous certain de vouloir enregistrer vos modifications?",
+
+// new in 0.6
+LockPanels:
+       "verrouiller les panneaux",
+UnlockPanels:
+       "déverrouiller les panneaux",
+CreateEmptyFile:
+       "créer un fichier vide",
+DownloadFileFromUrl:
+       "télécharger un fichier",
+DirectoryProperties:
+       "Propriétés de Dossier",
+SelectAll:
+       "tout sélectionner",
+SelectNone:
+       "tout désélectionner",
+InvertSelection:
+       "inverser la sélection",
+LoadingKFM:
+       "chargement de KFM",
+Name:
+       "Nom",
+FileDetails:
+       "Propriétés de Fichier",
+Search:
+       "Chercher",
+IllegalDirectoryName:
+       "Nom de dossier incorrect \"%1\"",
+RecursiveDeleteWarning:
+       "\"%1\" n'est pas vide\nVoulez-vous vraiment le supprimer ainsi que tout son contenu?\n*ATTENTION* CECI EST IRREVERSIBLE",
+RmdirFailed:
+       "impossible de supprimer le dossier \"%1\"",
+DirNotInDb:
+       "dossier inconnu dans la base de données",
+ShowPanel:
+       "afficher le panneau \"%1\"",
+ChangeCaption:
+       "Changer le Titre",
+NewDirectory:
+       "Nouveau Dossier",
+Upload:
+       "Envoyer",
+NewCaptionIsThisCorrect:
+       "Nouveau titre:\n%1\n\nEst-ce correct?",
+Close:
+       "fermer",
+Loading:
+       "chargement",
+AreYouSureYouWantToCloseKFM:
+       "Voulez-vous vraiment fermer la fenêtre KFM?",
+PleaseSelectFileBeforeRename:
+       "Veuillez sélectionner un fichier avant de renommer",
+RenameOnlyOneFile:
+       "Vous ne pouvez renommer qu'un fichier à la fois",
+RenameFileToWhat:
+       "Renommer le fichier \"%1\" en?",
+NoRestrictions:
+       "aucune restriction",
+Filename:
+       "nom de fichier",
+Maximise:
+       "agrandir",
+Minimise:
+       "réduire",
+AllowedFileExtensions:
+       "extensions permises",
+Filesize:
+       "taille",
+MoveDown:
+       "descendre",
+Mimetype:
+       "type MIME",
+MoveUp:
+       "monter",
+Restore:
+       "restorer",
+Caption:
+       "titre",
+CopyFromURL:
+       "Copier d'un URL",
+ExtractZippedFile:
+       "Décompresser le fichier",
+
+// new in 0.8
+ViewImage:
+       "voir l'image",
+ReturnThumbnailToOpener:
+       "renvoyer une vignette à l'éditeur",
+AddTagsToFiles:
+       "ajouter des libellés au(x) fichier(s)",
+RemoveTagsFromFiles:
+       "supprimer des libellés de ce(s) fichier(s)",
+HowWouldYouLikeToRenameTheseFiles:
+       "Comment souhaitez-vous renommer ces fichiers?\n\nexample: \"images-***.jpg\" les renommera en \"images-001.jpg\", \"images-002.jpg\", ...",
+YouMustPlaceTheWildcard:
+       "Vous devez utiliser le caractère joker * dans le modèle de nom",
+YouNeedMoreThan:
+       "Vous devez utiliser plus de %1 caractères * pour créer %2 noms",
+NoFilesSelected:
+       "aucun fichier sélectionné",
+Tags:
+       "libellés",
+IfYouUseMultipleWildcards:
+       "Si vous utilisez plusieurs jokers dans le modèle de nom, ils doivent être regroupés",
+NewCaption:
+       "Nouveau Titre",
+WhatMaximumSize:
+       "Quelle est la dimension maximum à renvoyer?",
+CommaSeparated:
+       "separé par des virgules",
+WhatIsTheNewTag:
+       "Quel est le nouveau libellé?\nPour plusieurs libellés, séparez-les avec des virgules.",
+WhichTagsDoYouWantToRemove:
+       "Quels libellés voulez-vous enlever?\nPour plusieurs libellés, séparez-les avec des virgules."
+
+,
+// New in 0.9
+AllFiles: "tous les fichiers",
+AndNMore: "...et %1 autres...",
+Browse: "Parcourir...",
+ExtractAfterUpload: "décompresser après envoi",
+NotAnImageOrImageDimensionsNotReported: "erreur: pas une image, ou impossible de déterminer ses dimensions",
+PermissionDeniedCannotDeleteFile: "permission refusée: impossible de supprimer le fichier",
+RenameTheDirectoryToWhat: "Renommer le dossier '%1' en?",
+RenamedDirectoryAs: "dossier '%1' renommé en '%2'",
+TheFilenameShouldEndWithN: "Le nom du fichier devrait finir par %1",
+WhatFilenameDoYouWantToUse: "Quel nom de fichier souhaitez-vous utiliser?"
+
+,
+// New in 1.0
+ZipUpFiles: "zipper les fichiers",
+Cancel: "annuler"
+       , // new in 1.2
+       Icons                   : "icons", // used to select mode of file view
+       ListView                : "list-view", // used to select mode of file view
+       SendToCms               : "send to CMS", // close KFM and return the selected files to the CMS
+       CannotMoveDirectory     : "permission denied: cannot move directory",
+       LastModified            : "last modified", // part of File Details
+       ImageDimensions         : "image dimensions", // part of File Details
+       CouldNotMoveFiles       : "error: could not move file[s]",
+       CopyFiles               : "copy files", // when dragging files to a directory, two choices appear - "copy files" and "move files"
+       MoveFiles               : "move files",
+       AboutKfm                : "about KFM",
+       Errors                  : "Errors",
+       Ok                      : "OK" // as in "OK / Cancel"
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/fr.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/fr.php
new file mode 100644 (file)
index 0000000..fbddf35
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *
+ * File Name: fr.php
+ *  French language file.
+ *
+ * File Authors:
+ *  Hubert Garrido (webmaster@liane.net)
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                => "\"%1\" existe déjà",
+       "errorInvalidID"               => "erreur: ID invalide",
+       "errorFileIDNotFound"          => "erreur: id de fichier #%1 introuvable dans la base",
+       "bannedFilenameExtension"      => "extension interdite dans le nom de fichier",
+       "cannotEditRestrictedExtension"=> "impossible de modifier \"%1\"\ndû à l'extension de fichier",
+       "cannotMoveIntoSelf"           => "impossible de déplacer un dossier dans un de ses sous-dossiers",
+       "cannotRenameFromTo"           => "impossible de renommer \"%1\" en \"%2\"",
+       "CMSRefusesFileDelete"         => "le CMS ne permet pas que \"%1\" soit supprimé",
+       "couldNotMoveDirectory"        => "impossible de déplacer le dossier \"%1\" en \"%2\"",
+       "couldNotCreateFile"           => "impossible de créer le fichier \"%1\"",
+       "errorSettingFileContent"      => "erreur en modifiant le contenu du fichier",
+       "failedCreateDirectoryCheck"   => "échec à la création du dossier \"%1\"\nvérifiez les permissions du système de fichiers",
+       "failedRenameDirectory"        => "échec en renommant le dossier",
+       "failedToSaveTmpFile"          => "échec en sauvegardant le fichier temporaire \"%1\" à l'emplacement \"%2\"",
+       "fileAlreadyExists"            => "un fichier de ce nom existe déjà",
+       "filesCopied"                  => "%1 fichiers copiés",
+       "illegalDirectoryName"         => "\"%1\" n'est pas un nom de dossier correct",
+       "illegalFileName"              => "\"%1\" n'est pas un nom de fichier correct",
+       "illegalTargetDirectory"       => "dossier de destination incorrect \"%1\"",
+       "isNotWritable"                => "impossible d'écrire dans \"%1\"",
+       "missingFileInSelection"       => "fichier manquant dans la sélection",
+       "noDataForFileID"              => "pas de données pour le fichier id \"%1\"",
+       "noDataForDirectoryID"         => "pas de données pour le dossier id \"%1\"",
+       "noNativeZipCommand"           => "commande \"zip\" introuvable sur le serveur",
+       "permissionDeniedUpload"       => "permission d'envoi refusée dans ce dossier",
+       "permissionDeniedCreateDirectory"=>"permission refusée: impossible de créer le dossier",
+       "permissionDeniedCreateFile"   => "permission refusée: impossible de créer le fichier",
+       "permissionDeniedDeleteDirectory"=>"permission refusée: impossible de supprimer le dossier",
+       "permissionDeniedDeleteFile"   => "permission refusée: impossible de supprimer le fichier",
+       "permissionDeniedEditDirectory"=> "permission refusée: impossible de modifier le dossier",
+       "permissionDeniedEditFile"     => "permission refusée: impossible de modifier le fichier",
+       "permissionDeniedMoveDirectory"=> "permission refusée: impossible de déplacer le dossier",
+       "permissionDeniedMoveFile"     => "permission refusée: impossible de déplacer le fichier",
+       "permissionDeniedRename"       => "permission refusée: impossible de renommer \"%1\"",
+       "permissionDeniedViewFile"     => "permission refusée: impossible d'afficher le fichier",
+       "searchResults"                => "résultats de recherche",
+       # 1.2
+       "fileNotCreatedDirUnwritable"    => "\"%1\" could not be created. The directory is not writable",
+       "fileNotDeletedUnwritable"       => "\"%1\" cannot be removed. (file not writable)",
+       "fileNotMovableUnwritable"       => "\"%1\" cannot be moved. (file not writable)",
+       "permissionDeniedManipImage"     => "permission denied: cannot manipulate images",
+       "imageNotWritable"               => "image is not writable",
+       "failedGetFileObject"            => "failed to retrieve File object",
+       "failedGetDirectoryObject"       => "failed to retrieve Directory object",
+       "failedDeleteFile"               => "failed to delete file \"%1\"",
+       "failedMoveFile"                 => "failed to move file \"%1\"",
+       "failedWriteToFile"              => "failed write to file \"%1\"",
+       "failedDownloadFromUrl"        => "failed to download from URL \"%1\""
+       ,
+       "file saved"                     => "file saved",
+       "files deleted"                  => "%1 files deleted",
+       "errorZipContainsBannedFilename" => "error: zip contains a banned filename",
+       "error: filename not allowed"    => "error: filename not allowed",
+       "error: url must begin with http"=> "error: url must begin with http",
+       "UNKNOWN TAG"                    => "UNKNOWN TAG \"%1\"",
+       "error: unzip failed"            => "error: unzip failed"
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/ga.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/ga.js
new file mode 100644 (file)
index 0000000..7edd9fb
--- /dev/null
@@ -0,0 +1,293 @@
+/*\r
+ * See ../license.txt for licensing\r
+ *\r
+ * For further information visit:\r
+ *     http://kfm.verens.com/\r
+ *\r
+ * File Name: ga.js\r
+ *     Irish language file.\r
+ *\r
+ * File Authors:\r
+ *     Kae Verens:     kae@verens.com\r
+ *  Ed Galligan:    ed.galligan@gmail.com (many fixes)\r
+ *  Kevin Scannell: kscanne@gmail.com (hints and grammatical software)\r
+ */\r
+\r
+kfm.lang=\r
+{\r
+Dir:\r
+       "ltr", // language direction\r
+ErrorPrefix:\r
+       "earráid: ",\r
+// what you see on the main page\r
+Directories:\r
+       "Comhadlannaí",\r
+CurrentWorkingDir:\r
+       "Comhadlann Oibre: \"%1\"",\r
+Logs:\r
+       "Loganna",\r
+FileUpload:\r
+       "Uasluchtaigh Comhad",\r
+DirEmpty:\r
+       "níl aon chomhaid in \"%1\"",\r
+\r
+// right click menu item directory\r
+// directory\r
+CreateSubDir:\r
+       "cruthaigh fochomhadlann",\r
+DeleteDir:\r
+       "scrios",\r
+RenameDir:\r
+       "athainmnigh",\r
+\r
+// file\r
+DeleteFile:\r
+       "scrios",\r
+RenameFile:\r
+       "athainmnigh",\r
+RotateClockwise:\r
+       "rothlaigh deiseal",\r
+RotateAntiClockwise:\r
+       "rothlaigh tuathal",\r
+ResizeImage:\r
+       "athraigh tomhas an pictiúr",\r
+ChangeCaption:\r
+       "athraigh ceannteideal",\r
+\r
+// create a file\r
+WhatFilenameToCreateAs:\r
+       "Cad is ainm den comhad?",\r
+AskIfOverwrite:\r
+       "Tá comhad leis an t-ainm \"%1\" ann cheana. Forscríobh?",\r
+NoForwardslash:\r
+       "\nNíl cead '/' a úsáid in ainm comhad",\r
+\r
+// messages management\r
+CreateDirMessage:\r
+       "Cruthaigh focomhadlann i \"%1\":",\r
+DelDirMessage:\r
+       "An bhfuil tú cinnte gur mian leat an comhadlann \"%1\" a scrios?",\r
+DelFileMessage:\r
+       "An bhfuil tú cinnte gur mian leat an comhad \"%1\" a scrios?",\r
+DelMultipleFilesMessage:\r
+       "An bhfuil tú cinnte gur mian leat na comhaid seo a scrios?\n\n'",\r
+DownloadFileFromMessage:\r
+       "Íosluchtaigh ó cén áit?",\r
+FileSavedAsMessage:\r
+       "Cad is mian leat an comhad a ainmniú?",\r
+\r
+// resize file\r
+CurrentSize:\r
+       "Tomhas Reatha: \"%1\" x \"%2\"\n",\r
+NewWidth:\r
+       "Leithead Nua?",\r
+NewWidthConfirmTxt:\r
+       "Leithead Nua: \"%1\"\n",\r
+NewHeight:\r
+       "Airde Nua?",\r
+NewHeightConfirmTxt:\r
+       "Airde Nua: \"%1\"\n\nAn bhfuil seo ceart?",\r
+\r
+// log messages\r
+RenamedFile:\r
+       "ag athainmniú ó \"%1\" go \"%2\".",\r
+DirRefreshed:\r
+       "comhadlannaí úraighte.",\r
+FilesRefreshed:\r
+       "comhaidí úraighte.",\r
+NotMoreThanOneFile:\r
+       "earráid: ní féidir ach comhad amháin a roghnú ag am amháin",\r
+UnknownPanelState:\r
+       "earráid: stáit painéil nach bhfuil fios faoi.",\r
+SetStylesError:\r
+       "earráid: ní féidir \"%1\" a chuir mar \"%2\.",\r
+NoPanel:\r
+       "earráid: níl painéil \"%1\" ann.",\r
+FileSelected:\r
+       "comhad roghnaithe: \"%1\"",\r
+Log_ChangeCaption:\r
+       "ag aithrú ceannteideal ó \"%1\" go \"%2\"",\r
+UrlNotValidLog:\r
+       "earráid: caithfidh an URL tosú le \"http:\"",\r
+MovingFilesTo:\r
+       "ag aistriú chomhaid [\"%1\"] go \"%2\"",\r
+\r
+// error messages\r
+DirectoryNameExists:\r
+       "tá comhadlann leis an t-ainm sin ann cheana.",\r
+FileNameNotAllowd:\r
+       "earráid: níl cead an comhad-ainm sin",\r
+CouldNotWriteFile:\r
+       "earráid: ní bhféidir an comhad \"%1\" a cruthú.",\r
+CouldNotRemoveDir:\r
+       "ní bhféidir an comhadlann a chealú.\ncaithfidh sé a bheith folamh",\r
+UrlNotValid:\r
+       "earráid: caithfidh an URL tosaidh le \"http:\"",\r
+CouldNotDownloadFile:\r
+       "earráid: ní féidir an comhad \"%1\" a íosluchtaigh.",\r
+FileTooLargeForThumb:\r
+       "earráid: tá \"%1\" rómhór chun thumbnail a cruthaigh. Caithfidh comhad níos beag a úsáid.",\r
+CouldntReadDir:\r
+       "earráid: ní féidir an chomhadlann a léamh",\r
+CannotRenameFile:\r
+       "earráid: ní féidir \"%1\" a ainmniú mar \"%2\"",\r
+FilenameAlreadyExists:\r
+       "earráid: tá comhad leis an ainm sin ann cheana",\r
+\r
+// new in 0.5\r
+EditTextFile:\r
+       "scríobh an téacs-chomhad",\r
+CloseWithoutSavingQuestion:\r
+       "An bhfuil tú cinnte gur mian leat an comhad a dhúnadh gan é a shábháil?",\r
+CloseWithoutSaving:\r
+       "Dún Gan Sábháil",\r
+SaveThenClose:\r
+       "Sábháil, agus Dún",\r
+SaveThenCloseQuestion:\r
+       "An bhfuil tú cinnte gur mian leat na hathruithe a shábháil?",\r
+\r
+// new in 0.6\r
+LockPanels:\r
+       "cuir glas ar na bpainéil",\r
+UnlockPanels:\r
+       "scaoil na painéil",\r
+CreateEmptyFile:\r
+       "cruthaigh comhad folamh",\r
+DownloadFileFromUrl:\r
+       "Íosluchtaigh ó URL",\r
+DirectoryProperties:\r
+       "Sonraí an Chomhadlann",\r
+SelectAll:\r
+       "roghnaigh gach rud",\r
+SelectNone:\r
+       "roghnaigh dada",\r
+InvertSelection:\r
+       "iompaigh an rogha",\r
+LoadingKFM:\r
+       "ag luchtú KFM",\r
+Name:\r
+       "ainm",\r
+FileDetails:\r
+       "Sonraí an Chomhad",\r
+Search:\r
+       "Cuardaigh",\r
+IllegalDirectoryName:\r
+       "níl cead comhadlann leis an t-ainm \"%1\"",\r
+RecursiveDeleteWarning:\r
+       "níl \"%1\" folamh\nAn bhfuil tú cinnte gur mhaith leat é agus a hábhair a scriosadh?\n*RABHADH* NÍ FÉIDIR É SEO A FHREASCHUR",\r
+RmdirFailed:\r
+       "theip ar scriosadh an comhadlann \"%1\"",\r
+DirNotInDb:\r
+       "níl an chomhadlann sa bhunachar sonraí",\r
+ShowPanel:\r
+       "taispeáin an phainéil \"%1\"",\r
+ChangeCaption:\r
+       "Athraigh an Cheannteideal",\r
+NewDirectory:\r
+       "Comhadlann Nua",\r
+Upload:\r
+       "Uasluchtaigh Comhad",\r
+NewCaptionIsThisCorrect:\r
+       "Ceannteideal Nua:\n%1\n\nAn bhfuil seo ceart?",\r
+Close:\r
+       "dún",\r
+Loading:\r
+       "ag luchtú",\r
+AreYouSureYouWantToCloseKFM:\r
+       "An bhfuil tú cinnte gur mhaith leat KFM a dhúnadh?",\r
+PleaseSelectFileBeforeRename:\r
+       "Roghnaigh comhad roimhe a athainmniú",\r
+RenameOnlyOneFile:\r
+       "Ní féidir ach comhad amháin a athainmniú ag aon am",\r
+RenameFileToWhat:\r
+       "Céard is mian leat \"%1\" a athainmniú?",\r
+NoRestrictions:\r
+       "gan srianta",\r
+Filename:\r
+       "ainm an comhad",\r
+Maximise:\r
+       "uastaigh",\r
+Minimise:\r
+       "íostaigh",\r
+AllowedFileExtensions:\r
+       "aicmí comhad ceadaithe",\r
+Filesize:\r
+       "tomhas an comhad",\r
+MoveDown:\r
+       "bog síos",\r
+Mimetype:\r
+       "aicmí MIME",\r
+MoveUp:\r
+       "bog suas",\r
+Restore:\r
+       "athbhunaigh",\r
+Caption:\r
+       "ceannteideal",\r
+CopyFromURL:\r
+       "Athscríobh ó URL",\r
+ExtractZippedFile:\r
+       "Bain as comhad Zip",\r
+\r
+// new in 0.8\r
+ViewImage:\r
+       "breathnaigh ar pictiúr",\r
+ReturnThumbnailToOpener:\r
+       "tabhair mionsamhail ar ais don oscailaitheoir",\r
+AddTagsToFiles:\r
+       "cur clibeanna le comhad(anna)",\r
+RemoveTagsFromFiles:\r
+       "tóg clibeanna ó comhad(anna)",\r
+HowWouldYouLikeToRenameTheseFiles:\r
+       "Conas ar mhaith leat na chomhaid a athainmniú?\n\ne.g.: ó \"images-***.jpg\" bainfidh tú \"images-001.jpg\", \"images-002.jpg\", ...",\r
+YouMustPlaceTheWildcard:\r
+       "Caithfidh leat an litir * a chur sa teimpléad",\r
+YouNeedMoreThan:\r
+       "Caithfidh níos mó ná %1 * litreacha a úsáid chun %2 ainm comhaid a dhéanamh",\r
+NoFilesSelected:\r
+       "níl aon chomhaid roghnaithe",\r
+Tags:\r
+       "clibeanna",\r
+IfYouUseMultipleWildcards:\r
+       "Má tá iolraí * úsáidte sa teimpléad, caithfidh na * a bheith le chéile",\r
+NewCaption:\r
+       "Ceannteideal Nua",\r
+WhatMaximumSize:\r
+       "Cén tomhas is mó is mian leat a chur ar ais?",\r
+CommaSeparated:\r
+       "scartha le camóig",\r
+WhatIsTheNewTag:\r
+       "Céard é an clib nua?\nLe clibeanna iolraithe a úsáid, idirscar le camóg.",\r
+WhichTagsDoYouWantToRemove:\r
+       "Cén clibeanna is mian leat a scriosadh?\nLe clibeanna iolraithe a scriosadh, idirscar le camóg."\r
+\r
+,\r
+// New in 0.9\r
+AllFiles: "all files",\r
+AndNMore: "...and %1 more...",\r
+Browse: "Browse...",\r
+ExtractAfterUpload: "extract after upload",\r
+NotAnImageOrImageDimensionsNotReported: "error: not an image, or image dimensions not reported",\r
+PermissionDeniedCannotDeleteFile: "permission denied: cannot delete file",\r
+RenameTheDirectoryToWhat: "Rename the directory '%1' to what?",\r
+RenamedDirectoryAs: "Renamed '%1' as '%2'",\r
+TheFilenameShouldEndWithN: "The filename should end with %1",\r
+WhatFilenameDoYouWantToUse: "What filename do you want to use?"\r
+\r
+,\r
+// New in 1.0\r
+ZipUpFiles: "zip up files",\r
+Cancel: "cancel"\r
+       , // new in 1.2\r
+       Icons                   : "icons", // used to select mode of file view\r
+       ListView                : "list-view", // used to select mode of file view\r
+       SendToCms               : "send to CMS", // close KFM and return the selected files to the CMS\r
+       CannotMoveDirectory     : "permission denied: cannot move directory",\r
+       LastModified            : "last modified", // part of File Details\r
+       ImageDimensions         : "image dimensions", // part of File Details\r
+       CouldNotMoveFiles       : "error: could not move file[s]",\r
+       CopyFiles               : "copy files", // when dragging files to a directory, two choices appear - "copy files" and "move files"\r
+       MoveFiles               : "move files",\r
+       AboutKfm                : "about KFM",\r
+       Errors                  : "Errors",\r
+       Ok                      : "OK" // as in "OK / Cancel"\r
+}\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/ga.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/ga.php
new file mode 100644 (file)
index 0000000..1d8fd39
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *
+ * File Name: ga.php
+ *  Irish language file.
+ *
+ * File Authors:
+ *  kae@verens.com
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                => "\"%1\" already exists",
+       "errorInvalidID"               => "error: invalid ID",
+       "errorFileIDNotFound"          => "error: file id #%1 not found in database",
+       "bannedFilenameExtension"      => "banned extension in file name",
+       "cannotEditRestrictedExtension"=> "cannot edit \"%1\"\nrestricted by file extension",
+       "cannotMoveIntoSelf"           => "cannot move a directory into its own sub-directory",
+       "cannotRenameFromTo"           => "cannot rename \"%1\" to \"%2\"",
+       "CMSRefusesFileDelete"         => "CMS does not allow \"%1\" to be deleted",
+       "couldNotMoveDirectory"        => "could not move directory \"%1\" to \"%2\"",
+       "couldNotCreateFile"           => "could not write file \"%1\"",
+       "errorSettingFileContent"      => "error setting file content",
+       "failedCreateDirectoryCheck"   => "failed to create directory \"%1\"\ncheck filesystem permissions",
+       "failedRenameDirectory"        => "failed to rename directory",
+       "failedToSaveTmpFile"          => "failure to save tmp file \"%1\" to location \"%2\"",
+       "fileAlreadyExists"            => "a file of that name already exists",
+       "filesCopied"                  => "%1 files copied",
+       "illegalDirectoryName"         => "\"%1\" is an illegal directory name",
+       "illegalFileName"              => "\"%1\" is an illegal file name",
+       "illegalTargetDirectory"       => "illegal target directory \"%1\"",
+       "isNotWritable"                => "\"%1\" is not writable",
+       "missingFileInSelection"       => "missing file in selection",
+       "noDataForFileID"              => "no data for file id \"%1\"",
+       "noDataForDirectoryID"         => "no data for directory id \"%1\"",
+       "noNativeZipCommand"           => "no \"zip\" command found on server",
+       "permissionDeniedUpload"       => "permission denied for upload to this directory",
+       "permissionDeniedCreateDirectory"=>"permission denied: cannot create directory",
+       "permissionDeniedCreateFile"   => "permission denied: cannot create file",
+       "permissionDeniedDeleteDirectory"=>"permission denied: cannot delete directory",
+       "permissionDeniedDeleteFile"   => "permission denied: cannot delete file",
+       "permissionDeniedEditDirectory"=> "permission denied: cannot edit directory",
+       "permissionDeniedEditFile"     => "permission denied: cannot edit file",
+       "permissionDeniedMoveDirectory"=> "permission denied: cannot move directory",
+       "permissionDeniedMoveFile"     => "permission denied: cannot move file",
+       "permissionDeniedRename"       => "permission denied: cannot rename \"%1\"",
+       "permissionDeniedViewFile"     => "permission denied: cannot view file",
+       "searchResults"                => "search results",
+       # 1.2
+       "fileNotCreatedDirUnwritable"    => "\"%1\" could not be created. The directory is not writable",
+       "fileNotDeletedUnwritable"       => "\"%1\" cannot be removed. (file not writable)",
+       "fileNotMovableUnwritable"       => "\"%1\" cannot be moved. (file not writable)",
+       "permissionDeniedManipImage"     => "permission denied: cannot manipulate images",
+       "imageNotWritable"               => "image is not writable",
+       "failedGetFileObject"            => "failed to retrieve File object",
+       "failedGetDirectoryObject"       => "failed to retrieve Directory object",
+       "failedDeleteFile"               => "failed to delete file \"%1\"",
+       "failedMoveFile"                 => "failed to move file \"%1\"",
+       "failedWriteToFile"              => "failed write to file \"%1\"",
+       "failedDownloadFromUrl"        => "failed to download from URL \"%1\""
+       ,
+       "file saved"                     => "file saved",
+       "files deleted"                  => "%1 files deleted",
+       "errorZipContainsBannedFilename" => "error: zip contains a banned filename",
+       "error: filename not allowed"    => "error: filename not allowed",
+       "error: url must begin with http"=> "error: url must begin with http",
+       "UNKNOWN TAG"                    => "UNKNOWN TAG \"%1\"",
+       "error: unzip failed"            => "error: unzip failed"
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/hu.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/hu.js
new file mode 100644 (file)
index 0000000..f3dac5e
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *     http                    ://kfm.verens.com/
+ *
+ * File Name: hu.js
+ *     Hungarian language file.
+ *
+ * File Authors:
+ *     Ujj-Mészáros István <info@styu.hu>
+ */
+
+kfm.lang={
+       AddTagsToFiles          : "Címke hozzáadása fájl(ok)hoz",
+       AllFiles                : "összes fájl",
+       AllowedFileExtensions   : "engedélyezett fájl kiterjesztések",
+       AndNMore                : "...és még %1...",
+       AreYouSureYouWantToCloseKFM: "Biztosan bezárja a KFM ablakát?",
+       AskIfOverwrite          : "A \"%1\" nevű fájl már létezik. Felülírjam?",
+       Browse                  : "Tallóz...",
+       Cancel                  : "mégse",
+       CouldNotWriteFile       : "hiba: nem írható a \"%1\" nevű fájl.",
+       CreateSubDir            : "alkönyvtár létrehozása",
+       CurrentWorkingDir       : "Jelenlegi munkakönyvtár: \"%1\"",
+       CouldNotRemoveDir       : "nem törölhető a könyvtár.\nellenőrizze, hogy üres-e",
+       CouldNotDownloadFile    : "hiba: nem lehet letölteni a \"%1\" nevű fájlt.",
+       CouldntReadDir          : "hiba: nem olvasható a könyvtár",
+       CreateEmptyFile         : "üres fájl létrehozása",
+       CloseWithoutSavingQuestion: "Biztosan mentés nélkül kívánja bezárni az ablakot?",
+       CloseWithoutSaving      : "Bezárás mentés nélkül",
+       CannotRenameFile        : "hiba: nem lehet átnevezni \"%1\" nevet \"%2\" nevűre",
+       ChangeCaption           : "felirat változtatása",                                                                                             // -------------------------
+       CreateDirMessage        : "Alkönyvtár létrehozása \"%1\" könyvtárban:",
+       CurrentSize             : "Altuális méret: \"%1\" x \"%2\"\n",
+       ChangeCaption           : "felirat változtatása",                                                                                             // -------------------------
+       Close                   : "bezár",
+       Caption                 : "felirat",
+       CommaSeparated          : "vesszővel tagolt",
+       CopyFromURL             : "Másolás URL-ből",
+       Dir                     : "ltr", // language direction
+       Directories             : "Könyvtárak",
+       DeleteFile              : "törlés",
+       DirEmpty                : "nem található fájl a \"%1\" nevű könyvtárban",
+       DeleteDir               : "törlés",
+       DelDirMessage           : "Tényleg töröljem a \"%1\" könyvtárt?",
+       DelFileMessage          : "Tényleg töröljem a \"%1\" fájlt?",
+       DelMultipleFilesMessage : "Tényleg töröljem az alábbi fájlokat?\n\n",
+       DownloadFileFromMessage : "Fájl letöltése honnan?",
+       DirRefreshed            : "könyvtárak frissítve.",
+       DirectoryNameExists     : "ezen a néven már létezik könyvtár.",
+       DownloadFileFromUrl     : "fájl letöltése URL-ből",
+       DirectoryProperties     : "Könyvtár tulajdonságok",
+       DirNotInDb              : "könyvtár nincs az adatbázisban",
+       ErrorPrefix             : "hiba: ",
+       EditTextFile            : "szöveges fájl szerkesztése",
+       ExtractAfterUpload      : "feltöltés után kibontás",
+       ExtractZippedFile       : "Zip-pelt fájl kibontása",
+       FileSavedAsMessage      : "Milyen néven legyen mentve a fájl?",
+       FileUpload              : "Fájl Feltöltés",
+       FilesRefreshed          : "fájlok frissítve.",
+       FileSelected            : "fájl kiválasztva: \"%1\"",
+       FileNameNotAllowd       : "hiba: fájlnév nem engedélyezett",
+       FileTooLargeForThumb    : "hiba: \"%1\" túl nagy bélyegkép létrehozáshoz. Le kell cserélni egy kisebb verzióra.",
+       FilenameAlreadyExists   : "hiba: ezen a néven már létezik fájl",
+       FileDetails             : "Fájl tulajdonságok",
+       Filename                : "fájlnév",
+       Filesize                : "fájlméret",
+       HowWouldYouLikeToRenameTheseFiles: "Az átnevezés módja az alábbi fájloknál?\n\npl.: az \"images-***.jpg\" a fájlokat \"images-001.jpg\", \"images-002.jpg\", ... módon nevezi át",
+       InvertSelection         : "kijelölés megfordítása",
+       IfYouUseMultipleWildcards: "If you use multiple wildcards in the filename template, they must be grouped together",
+       IllegalDirectoryName    : "érvénytelen könyvtárnév \"%1\"",
+       LockPanels              : "panelek zárolása",
+       Loading                 : "betöltés",
+       LoadingKFM              : "KFM betöltése",
+       Log_ChangeCaption: "\"%1\" felirat változtatása \"%2\"-ra",
+       Logs                    : "Naplók",
+       MovingFilesTo           : "fájlok mozgatása [\"%1\"]-ból \"%2\"-ba",
+       Maximise                : "maximalizálás",
+       Minimise                : "minimalizálás",
+       MoveDown                : "felfele mozgatás",
+       Mimetype                : "mimetype",
+       MoveUp                  : "lefele mozgatás",
+       NewCaptionIsThisCorrect : "Új felirat:\n%1\n\nEz helyes?",
+       Name                    : "név",
+       NewDirectory            : "Új könyvtár",
+       NoRestrictions          : "nincsenek megkötések",
+       NoForwardslash          : "\nNem használható '/' jel a fájlnévben",
+       NewWidth                : "Új szélesség?",
+       NoPanel                 : "hiba: a \"%1\" panel nem létezik.",
+       NotAnImageOrImageDimensionsNotReported: "hiba: nem kép, vagy a képméret nem lekérhető",
+       NewCaption              : "Új felirat",
+       NewWidthConfirmTxt      : "Új szélesség: \"%1\"\n",
+       NewHeight               : "Új magasság?",
+       NewHeightConfirmTxt     : "Új magasság: \"%1\"\n\nEz helyes?",
+       NotMoreThanOneFile      : "hiba: nem választható ki több fájl egyszerre",
+       NoFilesSelected         : "nincsenek fájlok kiválasztva",
+       PermissionDeniedCannotDeleteFile: "nincs jogosultág a fájl törlésére",
+       PleaseSelectFileBeforeRename: "Válasszon ki egy fájlt az átnevezés előtt",
+       RenameDir               : "átnevez",
+       RenameFile              : "átnevez",
+       RotateClockwise         : "forgatás órajárással egy irányba",
+       RotateAntiClockwise     : "forgatás órajárással ellentétesen ",
+       ResizeImage             : "kép átméretezése",
+       RenamedFile             : "fájl átnevezése \"%1\" -> \"%2\".",
+       Restore                 : "visszaállítás",
+       ReturnThumbnailToOpener : "bélyegkép vissza a szerkesztőbe",
+       RenameOnlyOneFile       : "Csak egy fájl nevezhető át egy időben",
+       RecursiveDeleteWarning  : "\"%1\" nem üres\nBiztosan töröljem az összes tartalmával együtt?\n*FIGYELEM* EZ VISSZAVONHATATLAN",
+       RmdirFailed             : "nem sikerült a \"%1\" könyvtár törlése",
+       RenamedDirectoryAs      : "Átnevezve '%1' -> '%2'",
+       RenameFileToWhat        : "Mire nevezzem át a \"%1\" fájlt?",
+       RenameTheDirectoryToWhat: "Mire nevezzem át a '%1' könyvtárt?",
+       RemoveTagsFromFiles     : "címke eltávolítása a fájl(ok)ból",
+       SetStylesError          : "hiba: nem állítható át \"%1\" -> \"%2\.",
+       SaveThenClose           : "Ment, majd Bezár",
+       SaveThenCloseQuestion   : "Biztosan mentsem a változtatásokat?",
+       SelectAll               : "mindent kijelöl",
+       SelectNone              : "kijelölés megszüntetése",
+       Search                  : "Keresés",
+       ShowPanel               : "\"%1\" panel mutatása",
+       Tags                    : "címkék",
+       TheFilenameShouldEndWithN: "A fájlnév %1-re végződhet",
+       UnknownPanelState       : "hiba: ismeretlen panel állapot.",
+       UrlNotValidLog          : "hiba: a URL-nek \"http:\"-el kell kezdődnie",
+       UnlockPanels            : "panelek zárolásának megszüntetése",
+       UrlNotValid             : "hiba: a URL-nek \"http:\"-el kell kezdődnie",
+       Upload                  : "Feltölt",
+       ViewImage               : "kép megtekintése",
+       WhatFilenameDoYouWantToUse: "Milyen fájlnevet akar használni?",
+       WhatFilenameToCreateAs  : "Milyen fájl legyen létrehozva?",
+       WhatMaximumSize         : "Milyen maximális méret adható vissza?",
+       WhatIsTheNewTag         : "Mi az új címke?\nTöbb címke megadható vesszővel elválasztva.",
+       WhichTagsDoYouWantToRemove: "Milyen címkék legyenek eltávolítva?\nTöbb címke megadható vesszővel elválasztva.",
+       YouMustPlaceTheWildcard : "A wildcard karaktert * a fájlnév template-ben kötelezően meg kell adni",
+       YouNeedMoreThan         : "Több, mint %1 * karakterre szükség van a %2 fájlnevekhez",
+       ZipUpFiles              : "Fájlok zip-pelése"
+       , // new in 1.2
+       Icons                   : "ikonok", // used to select mode of file view
+       ListView                : "lista nézet", // used to select mode of file view
+       SendToCms               : "CMS-be küldés", // close KFM and return the selected files to the CMS
+       CannotMoveDirectory     : "nincs jogosultsága a könyvtár mozgatásához",
+       LastModified            : "utoljára módosítva", // part of File Details
+       ImageDimensions         : "kép méretek", // part of File Details
+       CouldNotMoveFiles       : "hiba: nem mozgatható(ak) a fájl(ok)",
+       CopyFiles               : "fájlok másolása", // when dragging files to a directory, two choices appear - "copy files" and "move files"
+       MoveFiles               : "fájlok mozgatása",
+       AboutKfm                : "KFM névjegy",
+       Errors                  : "Hibák",
+       Ok                      : "OK" // as in "OK / Cancel"
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/hu.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/hu.php
new file mode 100644 (file)
index 0000000..8d97a2e
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *
+ * File Name: hu.php
+ *  Hungarian language file.
+ *
+ * File Authors:
+ *  Ujj-Mészáros István <info@styu.hu>
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                  => "\"%1\" már létezik",
+       "errorInvalidID"                 => "hiba: érvénytelen ID",
+       "errorFileIDNotFound"            => "hiba: a #%1 ID-jű fájl nem található az adatbázisban",
+       "bannedFilenameExtension"        => "tiltott kiterjesztés a fájlnévben",
+       "cannotEditRestrictedExtension"  => "\"%1\" nem szerkeszthető\na fájl kiterjesztés tiltott",
+       "cannotMoveIntoSelf"             => "egy könyvtár nem mozgatható a saját alkönyvtárába",
+       "cannotRenameFromTo"             => "nem átnevezhető \"%1\" -> \"%2\"",
+       "CMSRefusesFileDelete"           => "a CMS nem engedi a \"%1\" törlését",
+       "couldNotMoveDirectory"          => "nem mozgatható a könyvtár \"%1\" -> \"%2\"",
+       "couldNotCreateFile"             => "nem írható a \"%1\" fájl",
+       "errorSettingFileContent"        => "fájl tartalom állítás hiba",
+       "failedCreateDirectoryCheck"     => "nem sikerült a \"%1\" könyvtár létrehozása\nellenőrizze a fájlrendszer jogosultságokat",
+       "failedRenameDirectory"          => "nem sikerült a könyvtár átnevezése",
+       "failedToSaveTmpFile"            => "\"%1\" temp fájl mentése sikertelen a \"%2\" helyre",
+       "fileAlreadyExists"              => "ezen a néven már létezik fájl",
+       "filesCopied"                    => "%1 fájl másolása megtörtént",
+       "illegalDirectoryName"           => "\"%1\" érvénytelen könyvtárnév",
+       "illegalFileName"                => "\"%1\" érvénytelen fájlnév",
+       "illegalTargetDirectory"         => "érvénytelen célkönyvtár \"%1\"",
+       "isNotWritable"                  => "\"%1\" nem írható",
+       "missingFileInSelection"         => "hiányzó fájl a kijelölésben",
+       "noDataForFileID"                => "nincs adat a \"%1\" ID-jű fájlról",
+       "noDataForDirectoryID"           => "nincs adat a \"%1\" ID-jű könyvtárról",
+       "noNativeZipCommand"             => "nincs \"zip\" a szerveren",
+       "permissionDeniedUpload"         => "nincs jogosultság ebbe a könyvtárba feltölteni",
+       "permissionDeniedCreateDirectory"=> "nincs jogosultság könyvtár létrehozásához",
+       "permissionDeniedCreateFile"     => "nincs jogosultság fájl létrehozásához",
+       "permissionDeniedDeleteDirectory"=> "nincs jogosultság könyvtár törléséhez",
+       "permissionDeniedDeleteFile"     => "nincs jogosultság fájl törléséhez",
+       "permissionDeniedEditDirectory"  => "nincs jogosultság könyvtár szerkesztéshez",
+       "permissionDeniedEditFile"       => "nincs jogosultság fájl szerkesztéshez",
+       "permissionDeniedMoveDirectory"  => "nincs jogosultság könyvtár mozgatáshoz",
+       "permissionDeniedMoveFile"       => "nincs jogosultság fájl mozgatáshoz",
+       "permissionDeniedRename"         => "nincs jogosultság \"%1\" átnevezéséhez",
+       "permissionDeniedViewFile"       => "nincs jogosultság fájl megtekintéséhez",
+       "searchResults"                  => "találatok",
+       # 1.2
+       "fileNotCreatedDirUnwritable"    => "hiba: \"%1\" nem hozható létre. A könyvtár nem írható",
+       "fileNotDeletedUnwritable"       => "hiba: \"%1\" nem törölhető. (a fájl nem írható)",
+       "fileNotMovableUnwritable"       => "hiba: \"%1\" nem mozgatható. (a fájl nem írható)",
+       "permissionDeniedManipImage"     => "hiba: nincs jogosultság a kép szerkesztéséhez",
+       "imageNotWritable"               => "hiba: a kép nem írható",
+       "failedGetFileObject"            => "hiba: Fájl adatok lekérése sikertelen",
+       "failedGetDirectoryObject"       => "hiba: Könyvtár adatok lekérése sikertelen",
+       "failedDeleteFile"               => "hiba: \"%1\" fájl törlése sikertelen",
+       "failedMoveFile"                 => "hiba: \"%1\" fájl mozgatása sikertelen",
+       "failedWriteToFile"              => "hiba: \"%1\" fájl írása sikertelen",
+       "failedDownloadFromUrl"          => "hiba: \"%1\" URL-ből sikertelen letöltés",
+       
+       "file saved"                     => "fájl mentve",
+       "files deleted"                  => "%1 fájl törölve",
+       "errorZipContainsBannedFilename" => "hiba: a zip tiltott fájlnevet tartalmaz",
+       "hiba: filename not allowed"    => "hiba: fájlnév nem engedélyezett",
+       "hiba: url must begin with http"=> "hiba: a url-nek http-vel kell kezdődnie",
+       "UNKNOWN TAG"                    => "\"%1\" ISMERETLEN CÍMKE",
+       "hiba: unzip failed"            => "hiba: unzip (kibontás) sikertelen"
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/it.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/it.js
new file mode 100644 (file)
index 0000000..87eb5c1
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *     http://kfm.verens.com/
+ *
+ * File Name: it.js
+ *     Italian language file.
+ *
+ * File Authors:
+ *     stefano.luchetta@consiglio.marche.it
+ */
+
+kfm.lang=
+{
+Dir:
+       "ltr", // language direction
+ErrorPrefix:
+       "Errore: ",
+// what you see on the main page
+Directories:
+       "Cartelle",
+CurrentWorkingDir:
+       "Cartella corrente: \"%1\"",
+Logs:
+       "Registro operazioni",
+FileUpload:
+       "Carica file",
+DirEmpty:
+       "non ci sono file nella cartella \"%1\"",
+
+// right click menu item directory
+// directory
+CreateSubDir:
+       "crea una sotto cartella",
+DeleteDir:
+       "elimina",
+RenameDir:
+       "rinomina",
+
+// file
+DeleteFile:
+       "elimina",
+RenameFile:
+       "rinomina",
+RotateClockwise:
+       "ruota in senso orario",
+RotateAntiClockwise:
+       "ruota in senso antiorario",
+ResizeImage:
+       "ridimensiona immagine",
+ChangeCaption:
+       "cambia descrizione",
+
+// create a file
+WhatFilenameToCreateAs:
+       "In che formato deve essere creato il file?",
+AskIfOverwrite:
+       "Il file \"%1\" esiste. Sovrascriverlo?",
+NoForwardslash:
+       "\nNon puoi usare '/' nel nome del file",
+
+// messages management
+CreateDirMessage:
+       "Crea una sottocartella di \"%1\":",
+DelDirMessage:
+       "Vuoi cancellare la cartella \"%1\"?",
+DelFileMessage:
+       "Vuoi cancellare la cartella \"%1\"?",
+DelMultipleFilesMessage:
+       "Vuoi cancellare questi file?\n\n'",
+DownloadFileFromMessage:
+       "URL:",
+FileSavedAsMessage:
+       "In che formato deve essere salvato il file?",
+
+// resize file
+CurrentSize:
+       "Misure attuali: \"%1\" x \"%2\"\n",
+NewWidth:
+       "Nuova larghezza?",
+NewWidthConfirmTxt:
+       "Nuova larghezza: \"%1\"\n",
+NewHeight:
+       "Nuova altezza?",
+NewHeightConfirmTxt:
+       "Nuova altezza: \"%1\"\n\n dimensioni corrette?",
+
+// log messages
+RenamedFile:
+       "Rinomino il file \"%1\" a \"%2\".",
+DirRefreshed:
+       "Visualizzazione cartelle aggiornata.",
+FilesRefreshed:
+       "Visualizazzione file aggiornata.",
+NotMoreThanOneFile:
+       "errore: non puoi sceglierne piu\' di uno alla volta",
+UnknownPanelState:
+       "errore: stato del pannello sconosciuto.",
+// MissingDirWrapper:
+//     "error: missing directory wrapper: \"kfm_directories%1\".",
+SetStylesError:
+       "errore: impossibile impostare \"%1\" a \"%2\.",
+NoPanel:
+       "error: il pannello \"%1\" non esiste.",
+FileSelected:
+       "file selezionato: \"%1\"",
+Log_ChangeCaption:
+       "cambio descrizione di \"%1\" a \"%2\"",
+UrlNotValidLog:
+       "errore: la URL deve iniziare per \"http:\"",
+MovingFilesTo:
+       "sposto i file da [\"%1\"] a \"%2\"",
+
+// error messages
+DirectoryNameExists:
+       "una cartella con questo nome esiste già.",
+FileNameNotAllowd:
+       "errore: il nome del file non è corretto",
+CouldNotWriteFile:
+       "errore: non posso scrivere il file \"%1\".",
+CouldNotRemoveDir:
+       "non posso eliminare la cartella. Assicurarsi che sia vuota",
+UrlNotValid:
+       "errore: la URL deve iniziare con \"http:\"",
+CouldNotDownloadFile:
+       "errore: non posso scaricare il file \"%1\".",
+FileTooLargeForThumb:
+       "errore: \"%1\" è troppo grande per creare una anteprima. Diminuire le dimensioni del file.",
+CouldntReadDir:
+       "errore: non posso leggere la cartella",
+CannotRenameFile:
+       "errore: non posso rinominare \"%1\" a \"%2\"",
+FilenameAlreadyExists:
+       "errore: un file con questo nome esiste già",
+
+// new in 0.5
+EditTextFile:
+       "edita un file di testo",
+CloseWithoutSavingQuestion:
+       "Uscire senza salvare?",
+CloseWithoutSaving:
+       "Chiudi senza salvare",
+SaveThenClose:
+       "Salva, poi chiudi",
+SaveThenCloseQuestion:
+       "Salvare le modifiche?",
+
+// new in 0.6
+LockPanels:
+       "Blocca i pannelli",
+UnlockPanels:
+       "Sblocca i pannelli",
+CreateEmptyFile:
+       "Crea un file vuoto",
+DownloadFileFromUrl:
+       "Carica file da URL",
+DirectoryProperties:
+       "Proprietà cartella",
+SelectAll:
+       "seleziona tutto",
+SelectNone:
+       "deseleziona",
+InvertSelection:
+       "inverti selezione",
+LoadingKFM:
+       "Carico KFM",
+Name:
+       "nome",
+FileDetails:
+       "Proprietà file",
+Search:
+       "Cerca",
+IllegalDirectoryName:
+       "nome cartella non corretto: \"%1\"",
+RecursiveDeleteWarning:
+       "\"%1\" non è vuota\nCancellarla con tutto il suo contenuto?\n*ATTENZIONE* NON SARA\' PIU\' POSSIBILE RIPRISTINARLA",
+RmdirFailed:
+       "impossibile eliminare la cartella \"%1\"",
+DirNotInDb:
+       "la cartella non è nel database",
+ShowPanel:
+       "mostra pannello \"%1\"",
+ChangeCaption:
+       "cambia descrizione",
+NewDirectory:
+       "Nuova cartella",
+Upload:
+       "Carica",
+NewCaptionIsThisCorrect:
+       "Nuova descrizione:\n%1\n\nE\' corretta?",
+Close:
+       "chiudi",
+Loading:
+       "caricamento",
+AreYouSureYouWantToCloseKFM:
+       "Chiudere la finestra KFM?",
+PleaseSelectFileBeforeRename:
+       "seleziona un file!",
+RenameOnlyOneFile:
+       "Puoi rinominare solo un file alla volta",
+RenameFileToWhat:
+       "Occorre specificare il nuovo nome del file \"%1\"!",
+NoRestrictions:
+       "nessuna restrizione",
+Filename:
+       "nome file",
+Maximise:
+       "massimizza",
+Minimise:
+       "minimizza",
+AllowedFileExtensions:
+       "estensioni file consentite",
+Filesize:
+       "dimensione file",
+MoveDown:
+       "sposta giu\'",
+Mimetype:
+       "mimetype",
+MoveUp:
+       "sposta su\'",
+Restore:
+       "ripristina",
+Caption:
+       "descrizione",
+CopyFromURL:
+       "Copy from URL",
+ExtractZippedFile:
+       "Extract zipped file",
+
+// new in 0.8
+ViewImage:
+       "view image",
+ReturnThumbnailToOpener:
+       "return thumbnail to opener",
+AddTagsToFiles:
+       "add tags to file(s)",
+RemoveTagsFromFiles:
+       "remove tags from file(s)",
+HowWouldYouLikeToRenameTheseFiles:
+       "How would you like to rename these files?\n\nexample: \"images-***.jpg\" will rename files to \"images-001.jpg\", \"images-002.jpg\", ...",
+YouMustPlaceTheWildcard:
+       "You must place the wildcard character * somewhere in the filename template",
+YouNeedMoreThan:
+       "You need more than %1 * characters to create %2 filenames",
+NoFilesSelected:
+       "no files selected",
+Tags:
+       "tags",
+IfYouUseMultipleWildcards:
+       "If you use multiple wildcards in the filename template, they must be grouped together",
+NewCaption:
+       "New Caption",
+WhatMaximumSize:
+       "What maximum size should be returned?",
+CommaSeparated:
+       "comma-separated",
+WhatIsTheNewTag:
+       "What is the new tag?\nFor multiple tags, separate by commas.",
+WhichTagsDoYouWantToRemove:
+       "Which tags do you want to remove?\nFor multiple tags, separate by commas."
+
+,
+// New in 0.9
+AllFiles: "all files",
+AndNMore: "...and %1 more...",
+Browse: "Browse...",
+ExtractAfterUpload: "extract after upload",
+NotAnImageOrImageDimensionsNotReported: "error: not an image, or image dimensions not reported",
+PermissionDeniedCannotDeleteFile: "permission denied: cannot delete file",
+RenameTheDirectoryToWhat: "Rename the directory '%1' to what?",
+RenamedDirectoryAs: "Renamed '%1' as '%2'",
+TheFilenameShouldEndWithN: "The filename should end with %1",
+WhatFilenameDoYouWantToUse: "What filename do you want to use?"
+
+,
+// New in 1.0
+ZipUpFiles: "zip up files",
+Cancel: "cancel"
+       , // new in 1.2
+       Icons                   : "icons", // used to select mode of file view
+       ListView                : "list-view", // used to select mode of file view
+       SendToCms               : "send to CMS", // close KFM and return the selected files to the CMS
+       CannotMoveDirectory     : "permission denied: cannot move directory",
+       LastModified            : "last modified", // part of File Details
+       ImageDimensions         : "image dimensions", // part of File Details
+       CouldNotMoveFiles       : "error: could not move file[s]",
+       CopyFiles               : "copy files", // when dragging files to a directory, two choices appear - "copy files" and "move files"
+       MoveFiles               : "move files",
+       AboutKfm                : "about KFM",
+       Errors                  : "Errors",
+       Ok                      : "OK" // as in "OK / Cancel"
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/it.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/it.php
new file mode 100644 (file)
index 0000000..99feeca
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *
+ * File Name: it.php
+ *  Italian language file.
+ *
+ * File Authors:
+ *  kae@verens.com
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                => "\"%1\" already exists",
+       "errorInvalidID"               => "error: invalid ID",
+       "errorFileIDNotFound"          => "error: file id #%1 not found in database",
+       "bannedFilenameExtension"      => "banned extension in file name",
+       "cannotEditRestrictedExtension"=> "cannot edit \"%1\"\nrestricted by file extension",
+       "cannotMoveIntoSelf"           => "cannot move a directory into its own sub-directory",
+       "cannotRenameFromTo"           => "cannot rename \"%1\" to \"%2\"",
+       "CMSRefusesFileDelete"         => "CMS does not allow \"%1\" to be deleted",
+       "couldNotMoveDirectory"        => "could not move directory \"%1\" to \"%2\"",
+       "couldNotCreateFile"           => "could not write file \"%1\"",
+       "errorSettingFileContent"      => "error setting file content",
+       "failedCreateDirectoryCheck"   => "failed to create directory \"%1\"\ncheck filesystem permissions",
+       "failedRenameDirectory"        => "failed to rename directory",
+       "failedToSaveTmpFile"          => "failure to save tmp file \"%1\" to location \"%2\"",
+       "fileAlreadyExists"            => "a file of that name already exists",
+       "filesCopied"                  => "%1 files copied",
+       "illegalDirectoryName"         => "\"%1\" is an illegal directory name",
+       "illegalFileName"              => "\"%1\" is an illegal file name",
+       "illegalTargetDirectory"       => "illegal target directory \"%1\"",
+       "isNotWritable"                => "\"%1\" is not writable",
+       "missingFileInSelection"       => "missing file in selection",
+       "noDataForFileID"              => "no data for file id \"%1\"",
+       "noDataForDirectoryID"         => "no data for directory id \"%1\"",
+       "noNativeZipCommand"           => "no \"zip\" command found on server",
+       "permissionDeniedUpload"       => "permission denied for upload to this directory",
+       "permissionDeniedCreateDirectory"=>"permission denied: cannot create directory",
+       "permissionDeniedCreateFile"   => "permission denied: cannot create file",
+       "permissionDeniedDeleteDirectory"=>"permission denied: cannot delete directory",
+       "permissionDeniedDeleteFile"   => "permission denied: cannot delete file",
+       "permissionDeniedEditDirectory"=> "permission denied: cannot edit directory",
+       "permissionDeniedEditFile"     => "permission denied: cannot edit file",
+       "permissionDeniedMoveDirectory"=> "permission denied: cannot move directory",
+       "permissionDeniedMoveFile"     => "permission denied: cannot move file",
+       "permissionDeniedRename"       => "permission denied: cannot rename \"%1\"",
+       "permissionDeniedViewFile"     => "permission denied: cannot view file",
+       "searchResults"                => "search results",
+       # 1.2
+       "fileNotCreatedDirUnwritable"    => "\"%1\" could not be created. The directory is not writable",
+       "fileNotDeletedUnwritable"       => "\"%1\" cannot be removed. (file not writable)",
+       "fileNotMovableUnwritable"       => "\"%1\" cannot be moved. (file not writable)",
+       "permissionDeniedManipImage"     => "permission denied: cannot manipulate images",
+       "imageNotWritable"               => "image is not writable",
+       "failedGetFileObject"            => "failed to retrieve File object",
+       "failedGetDirectoryObject"       => "failed to retrieve Directory object",
+       "failedDeleteFile"               => "failed to delete file \"%1\"",
+       "failedMoveFile"                 => "failed to move file \"%1\"",
+       "failedWriteToFile"              => "failed write to file \"%1\"",
+       "failedDownloadFromUrl"        => "failed to download from URL \"%1\""
+       ,
+       "file saved"                     => "file saved",
+       "files deleted"                  => "%1 files deleted",
+       "errorZipContainsBannedFilename" => "error: zip contains a banned filename",
+       "error: filename not allowed"    => "error: filename not allowed",
+       "error: url must begin with http"=> "error: url must begin with http",
+       "UNKNOWN TAG"                    => "UNKNOWN TAG \"%1\"",
+       "error: unzip failed"            => "error: unzip failed"
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/nl.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/nl.js
new file mode 100644 (file)
index 0000000..2b32a69
--- /dev/null
@@ -0,0 +1,285 @@
+/*\r
+ * File Name: nl.js\r
+ *     Dutch language file.\r
+ *\r
+ * File Author:\r
+ *     Roy Lubbers (roy@cns-it.nl)\r
+ */\r
+\r
+kfm.lang=\r
+{\r
+\r
+Dir:\r
+       "ltr",\r
+ErrorPrefix:\r
+       "Fout: ",\r
+\r
+Directories:\r
+       "Mappen",\r
+CurrentWorkingDir:\r
+       "Huidige map: \"%1\"",\r
+Logs:\r
+       "Logs",\r
+FileUpload:\r
+       "Bestand uploaden",\r
+DirEmpty:\r
+       "Geen bestanden gevonden in \"%1\"",\r
+\r
+\r
+\r
+CreateSubDir:\r
+       "Submap maken",\r
+DeleteDir:\r
+       "map verwijderen",\r
+RenameDir:\r
+       "map hernoemen",\r
+\r
+DeleteFile:\r
+       "bestand verwijderen",\r
+RenameFile:\r
+       "bestand hernoemen",\r
+RotateClockwise:\r
+       "met de klok mee draaien",\r
+RotateAntiClockwise:\r
+       "tegen de klok in draaien",\r
+ResizeImage:\r
+       "Formaat wijzigen",\r
+ChangeCaption:\r
+       "Titel wijzigen",\r
+\r
+\r
+WhatFilenameToCreateAs:\r
+       "Welk bestandstype moet worden gemaakt?",\r
+AskIfOverwrite:\r
+       "Bestand \"%1\" bestaat al. Overschrijven?",\r
+NoForwardslash:\r
+       "\nEr mag geen '/' voorkomen in de bestandsnaam.",\r
+\r
+\r
+CreateDirMessage:\r
+       "Maak een submap in \"%1\":",  \r
+DelDirMessage:\r
+       "Weet u zeker dat u map \"%1\" wilt verwijderen?", \r
+DelFileMessage:\r
+       "Weet u zeker dat u het bestand  \"%1\" wilt verwijderen?",\r
+DelMultipleFilesMessage:\r
+       "Weet u zeker dat u de volgende bestanden verwijderen wilt? \n\n'",\r
+DownloadFileFromMessage : "Bestand van waar downloaden?", \r
+FileSavedAsMessage:\r
+       "Als wat moet het bestand opgeslagen worden?",\r
+\r
+CurrentSize:\r
+       "Huidige grootte: \"%1\" x \"%2\"", \r
+NewWidth:\r
+       "Nieuwe breedte?",\r
+NewWidthConfirmTxt:\r
+       "Nieuwe breedte?: \"%1\"",\r
+NewHeight:\r
+       "Nieuwe hoogte?",\r
+NewHeightConfirmTxt:\r
+       "Nieuwe hoogte: \"%1\"\n\nIs dit juist?",\r
+\r
+\r
+RenamedFile:\r
+       "Bestandsnaam \"%1\" wijzigen in \"%2\".", \r
+DirRefreshed:\r
+       "Mappen opnieuw geladen.", \r
+FilesRefreshed:\r
+       "Bestanden opnieuw geladen.",\r
+NotMoreThanOneFile:\r
+       "Fout: U kunt niet meer dan één bestand selecteren.", \r
+UnknownPanelState:\r
+       "Fout: Onbekende paneelstatus.", \r
+MissingDirWrapper:\r
+       "Fout: Mapvenster ontbreekt: \"%1\".", \r
+SetStylesError:\r
+       "Fout: Kan \"%1\" niet wijzigen in \"%2\.", \r
+NoPanel:\r
+       "Fout: Paneel \"%1\" bestaat niet.",\r
+FileSelected:\r
+       "Bestand geselecteerd: \"%1\"", \r
+Log_ChangeCaption:\r
+       "Wijzig titel \"%1\" in \"%2\"", \r
+UrlNotValidLog:\r
+       "Fout: URL moet beginnen met: http", \r
+MovingFilesTo:\r
+       "Verplaats bestanden [\"%1\"] naar \"%2\"", \r
+\r
+DirectoryNameExists:\r
+       "Een map met dezelde naam bestaat al.", \r
+FileNameNotAllowd:\r
+       "Fout: Bestandsnaam niet toegestaan.",\r
+CouldNotWriteFile:\r
+       "Fout: Bestand \"%1\" kan niet opgeslagen worden.",\r
+CouldNotRemoveDir:\r
+       "kan map niet verwijderen.\nControleer of deze leeg is.",\r
+UrlNotValid:\r
+       "Fout: URL moet beginnen met: http", \r
+CouldNotDownloadFile:\r
+       "Fout: kan bestand \"%1\" niet downloaden.",\r
+FileTooLargeForThumb:\r
+       "Fout: De afbeelding \"%1\" is te groot om een thumbnail te maken. Vervang dit bestand voor een kleiner formaat.", \r
+CouldntReadDir:\r
+       "Kan de map niet openen.",\r
+CannotRenameFile:\r
+       "Fout: Kan \"%1\" niet wijzigen in \"%2\".",\r
+FilenameAlreadyExists:\r
+       "Fout: Een bestand met dezelfde naam bestaat al.",\r
+\r
+// new in 0.5\r
+EditTextFile:\r
+       "bewerk tekstbestand",\r
+CloseWithoutSavingQuestion:\r
+       "Weet u zeker dat u wilt sluiten zonder de wijzigingen op te slaan?",\r
+CloseWithoutSaving:\r
+       "Sluiten zonder opslaan",\r
+SaveThenClose:\r
+       "Opslaan, dan sluiten",\r
+SaveThenCloseQuestion:\r
+       "Weet u zeker dat u de wijzigingen wilt opslaan?",\r
+\r
+// new in 0.6\r
+LockPanels:\r
+       "panelen vastzetten",\r
+UnlockPanels:\r
+       "panelen los maken",\r
+CreateEmptyFile:\r
+       "maak leeg bestand",\r
+DownloadFileFromUrl:\r
+       "download bestand van URL",\r
+DirectoryProperties:\r
+       "Map Eigenschappen",\r
+SelectAll:\r
+       "Alles selecteren",\r
+SelectNone:\r
+       "Niets selecteren",\r
+InvertSelection:\r
+       "Selectie omdraaien",\r
+LoadingKFM:\r
+       "laden KFM",\r
+Name:\r
+       "naam",\r
+FileDetails:\r
+       "Bestand Details",\r
+Search:\r
+       "Zoek",\r
+IllegalDirectoryName:\r
+       "ongeldige mapnaam \"%1\"",\r
+RecursiveDeleteWarning:\r
+       "\"%1\" is niet leeg\nWeet u zeker dat u dit wilt verwijderen met alle onderliggende bestanden en mappen?\n*WAARSCHUWING* DIT IS NIET TERUG TE DRAAIEN",\r
+RmdirFailed:\r
+       "kan map niet verwijderen \"%1\"",\r
+DirNotInDb:\r
+       "map niet in database",\r
+ShowPanel:\r
+       "laat paneel \"%1\" zien",\r
+ChangeCaption:\r
+       "Wijzig Titel",\r
+NewDirectory:\r
+       "Nieuwe Map",\r
+Upload:\r
+       "Upload",\r
+NewCaptionIsThisCorrect:\r
+       "Nieuwe Titel:\n%1\n\nIs dit juist?",\r
+Close:\r
+       "sluit",\r
+Loading:\r
+       "laden",\r
+AreYouSureYouWantToCloseKFM:\r
+       "Weet u zeker dat u het KFM venster wilt sluiten?",\r
+PleaseSelectFileBeforeRename:\r
+       "Selecteer een bestand voordat u het wil hernoemen",\r
+RenameOnlyOneFile:\r
+       "U kunt één bestand per keer hernoemen",\r
+RenameFileToWhat:\r
+       "Hernoem bestand \"%1\" naar?",\r
+NoRestrictions:\r
+       "geen restricties",\r
+Filename:\r
+       "bestandsnaam",\r
+Maximise:\r
+       "maximalizeren",\r
+Minimise:\r
+       "minimalizeren",\r
+AllowedFileExtensions:\r
+       "toegestane bestandsextensies",\r
+Filesize:\r
+       "bestandsgrootte",\r
+MoveDown:\r
+       "naar beneden",\r
+Mimetype:\r
+       "mimetype",\r
+MoveUp:\r
+       "naar boven",\r
+Restore:\r
+       "herstel",\r
+Caption:\r
+       "titel",\r
+CopyFromURL:\r
+       "Kopieren van URL",\r
+ExtractZippedFile:\r
+       "Uitpakken zipbestand",\r
+\r
+// new in 0.8\r
+ViewImage:\r
+       "bekijk afbeelding",\r
+ReturnThumbnailToOpener:\r
+       "breng thumbnail terug naar opener",\r
+AddTagsToFiles:\r
+       "voeg labels toe aan bestand(en)",\r
+RemoveTagsFromFiles:\r
+       "verwijder labels van bestand(en)",\r
+HowWouldYouLikeToRenameTheseFiles:\r
+       "Hoe wilt u deze bestanden hernoemen?\n\nvoorbeeld: \"afbeelding-***.jpg\" zal bestanden hernoemen naar \"afbeelding-001.jpg\", \"afbeelding-002.jpg\", ...",\r
+YouMustPlaceTheWildcard:\r
+       "Plaats de wildcard karakter * ergens in de bestandssjabloon",\r
+YouNeedMoreThan:\r
+       "U hebt meer dan %1 * karakters nodig om %2 bestanden te kunnen maken",\r
+NoFilesSelected:\r
+       "geen bestanden geselecteerd",\r
+Tags:\r
+       "labels",\r
+IfYouUseMultipleWildcards:\r
+       "Wanneer u meerdere wildcards in de bestandssjabloon gebruikt dan moeten u groeperen.",\r
+NewCaption:\r
+       "Nieuwe titel",\r
+WhatMaximumSize:\r
+       "Welke maximale grootte moet er weergegeven worden?",\r
+CommaSeparated:\r
+       "komma-gescheiden",\r
+WhatIsTheNewTag:\r
+       "Wat is de nieuwe label?\nMeerdere labels moeten worden gescheiden door komma's.",\r
+WhichTagsDoYouWantToRemove:\r
+       "Welke labels wilt u verwijderen?\nMeerdere labels moeten worden gescheiden door komma's."\r
+\r
+,\r
+// New in 0.9\r
+AllFiles: "alle bestanden",\r
+AndNMore: "...en %1 meer...",\r
+Browse: "Bladeren...",\r
+ExtractAfterUpload: "uitpakken na upload",\r
+NotAnImageOrImageDimensionsNotReported: "fout: geen afbeelding of geen bestandsdimensies aanwezig",\r
+PermissionDeniedCannotDeleteFile: "toegang geweigerd: kan bestand niet verwijderen",\r
+RenameTheDirectoryToWhat: "Hernoem map '%1' naar?",\r
+RenamedDirectoryAs: "'%1' hernoemd als '%2'",\r
+TheFilenameShouldEndWithN: "Bestandsnaam moet eindigen met %1",\r
+WhatFilenameDoYouWantToUse: "Welke bestandsnaam wilt u gebruiken?"\r
+\r
+,\r
+// New in 1.0\r
+ZipUpFiles: "bestanden inpakken",\r
+Cancel: "annuleren"\r
+       , // new in 1.2\r
+       Icons                   : "iconen", // used to select mode of file view\r
+       ListView                : "lijstweergave", // used to select mode of file view\r
+       SendToCms               : "verzenden CMS", // close KFM and return the selected files to the CMS\r
+       CannotMoveDirectory     : "toegang geweigerd: kan map niet verplaatsen",\r
+       LastModified            : "laatst aangepast", // part of File Details\r
+       ImageDimensions         : "afbeelingdimenties", // part of File Details\r
+       CouldNotMoveFiles       : "fout: kan bestand[en] niet verplaatsen",\r
+       CopyFiles               : "bestanden kopieren", // when dragging files to a directory, two choices appear - "copy files" and "move files"\r
+       MoveFiles               : "bestanden verplaatsen",\r
+       AboutKfm                : "over KFM",\r
+       Errors                  : "Fouten",\r
+       Ok                      : "OK" // as in "OK / Cancel"\r
+}\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/nl.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/nl.php
new file mode 100644 (file)
index 0000000..4c2538c
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *
+ * File Name: nl.php
+ *  Dutch language file.
+ *
+ * File Authors:
+ *  Roy Lubbers (roy@cns-it.nl)
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                => "\"%1\" bestaat al",
+       "errorInvalidID"               => "fout: ongeldige ID",
+       "errorFileIDNotFound"          => "fout: bestands-id #%1 niet gevonden in database",
+       "bannedFilenameExtension"      => "verbannen extensie in bestandsnaam",
+       "cannotEditRestrictedExtension"=> "kan \"%1\" niet bewerken\nrestrictie op bestandsextensie",
+       "cannotMoveIntoSelf"           => "kan map niet verplaatsen naar eigen submap",
+       "cannotRenameFromTo"           => "kan \"%1\" niet hernoemen naar \"%2\"",
+       "CMSRefusesFileDelete"         => "CMS staat niet toe dat \"%1\" verwijderd wordt",
+       "couldNotMoveDirectory"        => "kan map \"%1\" niet verplaatsen naar \"%2\"",
+       "couldNotCreateFile"           => "kan bestand \"%1\" niet schrijven",
+       "errorSettingFileContent"      => "fout aanpassen bestandsinhoud",
+       "failedCreateDirectoryCheck"   => "kan map \"%1\" niet maken\ncontroleer bestandssysteempermissies",
+       "failedRenameDirectory"        => "kan map niet hernoemen",
+       "failedToSaveTmpFile"          => "kan tmp-bestand \"%1\" niet opslaan op locatie \"%2\"",
+       "fileAlreadyExists"            => "een bestand met dezelfde naam bestaat al",
+       "filesCopied"                  => "%1 bestanden gekopieerd",
+       "illegalDirectoryName"         => "\"%1\" is een ongeldige mapnaam",
+       "illegalFileName"              => "\"%1\" is een ongeldige bestandsnaam",
+       "illegalTargetDirectory"       => "ongeldige doelmap \"%1\"",
+       "isNotWritable"                => "\"%1\" is niet schrijfbaar",
+       "missingFileInSelection"       => "mis bestand in selectie",
+       "noDataForFileID"              => "geen gegevens voor bestands-id \"%1\"",
+       "noDataForDirectoryID"         => "geen gegeven voor map-id \"%1\"",
+       "noNativeZipCommand"           => "geen \"zip\" commando gevonden op de server",
+       "permissionDeniedUpload"       => "toegang geweigerd voor uploaden naar deze map",
+       "permissionDeniedCreateDirectory"=>"toegang geweigerd: kan map niet maken",
+       "permissionDeniedCreateFile"   => "toegang geweigerd: kan bestand niet maken",
+       "permissionDeniedDeleteDirectory"=>"toegang geweigerd: kan map niet verwijderen",
+       "permissionDeniedDeleteFile"   => "toegang geweigerd: kan bestand niet verwijderen",
+       "permissionDeniedEditDirectory"=> "toegang geweigerd: kan map niet bewerken",
+       "permissionDeniedEditFile"     => "toegang geweigerd: kan bestand niet bewerken",
+       "permissionDeniedMoveDirectory"=> "toegang geweigerd: kan map niet verplaatsen",
+       "permissionDeniedMoveFile"     => "toegang geweigerd: kan bestand niet verplaatsen",
+       "permissionDeniedRename"       => "toegang geweigerd: kan \"%1\" niet hernoemen",
+       "permissionDeniedViewFile"     => "toegang geweigerd: kan bestand niet bekijken",
+       "searchResults"                => "zoekresultaten",
+       # 1.2
+       "fileNotCreatedDirUnwritable"    => "\"%1\" kan niet worden gemaakt. Kan niet schrijven in map.",
+       "fileNotDeletedUnwritable"       => "\"%1\" kan niet worden verwijdert. (bestand is niet schrijfbaar)",
+       "fileNotMovableUnwritable"       => "\"%1\" kan niet worden verplaatst. (bestand is niet schrijfbaar)",
+       "permissionDeniedManipImage"     => "toegang geweigerd: kan afbeeldingen niet manipuleren",
+       "imageNotWritable"               => "afbeelding is niet schrijfbaar",
+       "failedGetFileObject"            => "ophalen van bestandsobject is mislukt",
+       "failedGetDirectoryObject"       => "ophalen van mapobject is mislukt",
+       "failedDeleteFile"               => "verwijderen bestand \"%1\" is mislukt",
+       "failedMoveFile"                 => "verplaatsen bestand \"%1\" is mislukt",
+       "failedWriteToFile"              => "schrijven naar bestand \"%1\" is mislukt",
+       "failedDownloadFromUrl"        => "downloaden van URL \"%1\" is mislukt"
+       ,
+       "file saved"                     => "bestand opgeslagen",
+       "files deleted"                  => "%1 bestanden verwijderd",
+       "errorZipContainsBannedFilename" => "fout: zip bevat een ongeldige bestandsnaam",
+       "error: filename not allowed"    => "fout: bestandsnaam niet toegestaan",
+       "error: url must begin with http"=> "fout: url moet beginnen met http",
+       "UNKNOWN TAG"                    => "ONBEKEND TAG \"%1\"",
+       "error: unzip failed"            => "fout: uitpakken is mislukt"
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/pl.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/pl.js
new file mode 100644 (file)
index 0000000..206bc5b
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *     http://kfm.verens.com/
+ *
+ * File Name: pl.js
+ *     English language file.
+ *
+ * File Authors:
+ *     jan.kurek@gmail.com
+ */
+
+kfm.lang={
+       AddTagsToFiles: "dodaj tagi",
+       AllowedFileExtensions: "dopuszczalne rozszerzenia plików",
+       AreYouSureYouWantToCloseKFM: "Czy na pewno chcesz zamknąć okno KFM ?",
+       AskIfOverwrite: "Plik \"%1\" już istnieje. Nadpisać?",
+       CouldNotWriteFile: "błąd: nie mogę zapisać pliku \"%1\".",
+       CreateSubDir: "dodaj podkatalog",
+       CurrentWorkingDir: "Obecny Katalog Roboczy: \"%1\"",
+       CouldNotRemoveDir: "nie mogę usunąć katalogu.\nupewnij się, że jest on pusty",
+       CouldNotDownloadFile: "błąd: nie mogę pobrać pliku \"%1\".",
+       CouldntReadDir: "błąd: nie mogę odczytać katalogu",
+       CreateEmptyFile: "stwórz pusty plik",
+       CloseWithoutSavingQuestion: "Czy na pewno zamknąć bez zapisywania?",
+       CloseWithoutSaving: "Zamknij Bez Zapisywania",
+       CannotRenameFile: "błąd: nie mogę zmienić nazwy \"%1\" na \"%2\"",
+       ChangeCaption: "zmień podpis",
+       CreateDirMessage: "Dodaj podkatalog w \"%1\":",
+       CurrentSize: "Obecny rozmiar: \"%1\" x \"%2\"\n",
+       ChangeCaption: "Zmień Podpis",
+       Close: "zamknij",
+       Caption: "podpis",
+       CommaSeparated: "rozdzielone przecinkami",
+       CopyFromURL: "Kopiuj z adresu URL",
+       Dir: "ltr", // language direction
+       Directories: "Katalogi",
+       DeleteFile: "usuń plik",
+       DirEmpty: "nie znaleziono plików w \"%1\"",
+       DeleteDir: "usuń katalog",
+       DelDirMessage: "Czy na pewno usunąć katalog \"%1\"?",
+       DelFileMessage: "Czy na pewno usunąć plik \"%1\"",
+       DelMultipleFilesMessage: "Czy na pewno usunąć te pliki?\n\n",
+       DownloadFileFromMessage: "Skąd ściągnąć plik?",  //??
+       DirRefreshed: "katalog odświeżony.",
+       DirectoryNameExists: "katalog z taką nazwą już istnieje.",
+       DownloadFileFromUrl: "ściągnij plik z adresu URL",
+       DirectoryProperties: "Właściwości Katalogu",
+       DirNotInDb: "brak katalogu w bazie",
+       ErrorPrefix: "błąd: ",
+       EditTextFile: "edytuj plik tekstowy",
+       ExtractZippedFile: "Rozpakuj archiwum",
+       FileSavedAsMessage: "Jak powinien zostać zapisany plik?", //??
+       FileUpload: "Wysyłanie Pliku",
+       FilesRefreshed: "pliki odświeżone.",
+       FileSelected: "zaznaczony plik: \"%1\"",
+       FileNameNotAllowd: "błąd: niedopuszczalna nazwa pliku",
+       FileTooLargeForThumb: "błąd: \"%1\" jest za duży by wykonać miniaturkę. Zastąp plik jego mniejszą wersją.",
+       FilenameAlreadyExists: "błąd: plik o takiej nazwie już istnieje",
+       FileDetails: "Szczegóły Pliku",
+       Filename: "nazwa pliku",
+       Filesize: "rozmiar pliku",
+       HowWouldYouLikeToRenameTheseFiles: "W jaki sposób chciałbyś zmienić nazwę tych plików?\n\nnp: \"images-***.jpg\" zmieni nazwy plików na \"images-001.jpg\", \"images-002.jpg\", ...",
+       InvertSelection: "odwróć zaznaczenie",
+       IfYouUseMultipleWildcards: "Gwiazdki * w szablonie nazwy pliku musisz umieścić razem",
+       IllegalDirectoryName: "niedozwolona nazwa katalogu \"%1\"",
+       LockPanels: "zablokuj panele",
+       Loading: "ładowanie",
+       LoadingKFM: "ładowanie KFM",
+       Log_ChangeCaption: "zmiana podpisu z \"%1\" na \"%2\"",
+       Logs: "Logi",
+       MovingFilesTo: "przenoszenie plików z [\"%1\"] do \"%2\"",
+       Maximise: "zmaksymalizuj",
+       Minimise: "zminimalizuj",
+       MoveDown: "przesuń w dół",
+       Mimetype: "Typ MIME",
+       MoveUp: "przesuń w górę",
+       NewCaptionIsThisCorrect: "Nowy Podpis:\n%1\n\nZatwierdzić?",
+       Name: "nazwa",
+       NewDirectory: "Nowy Katalog",
+       NoRestrictions: "brak ograniczeń",
+       NoForwardslash: "\nNie można używać '/' w nazwach plików",
+       NewWidth: "Nowa Szerokość?",
+       NoPanel: "błąd: panel \"%1\" nie istnieje.",
+       NewCaption: "Nowy Podpis",
+       NewWidthConfirmTxt: "Nowa Szerokość: \"%1\"\n",
+       NewHeight: "Nowa Wysokość?",
+       NewHeightConfirmTxt: "Nowa Wysokość: \"%1\"\n\nZatwierdzić?",
+       NotMoreThanOneFile: "błąd: nie można wybrać więcej niż jednego pliku jednocześnie",
+       NoFilesSelected: "brak zaznaczonych plików",
+       PleaseSelectFileBeforeRename: "Zaznacz plik, którego nazwę chcesz zmienić",
+       RenameDir: "zmień nazwę",
+       RenameFile: "zmień nazwę",
+       RotateClockwise: "odwróć zgodnie z ruchem wskazówek",
+       RotateAntiClockwise: "odwróć przeciwnie do ruchu wskazówek",
+       ResizeImage: "zmień rozmiar obrazka",
+       RenamedFile: "zmienianie nazwy pliku z \"%1\" na \"%2\".",
+       Restore: "przywróć",
+       ReturnThumbnailToOpener: "przekaż miniaturę do edytora",
+       RenameOnlyOneFile: "Możesz zmienić nazwę tylko jednego pliku jednocześnie",
+       RecursiveDeleteWarning: "\"%1\" nie jest pusty\nCzy jesteś pewny, że chcesz usunąć katalog z całą zawartością?\n*UWAGA* TA OPERACJA JEST NIEODWRACALNA",
+       RmdirFailed: "nie udało się usunąć katalogu \"%1\"",
+       RenameFileToWhat: "Na co zmienić nazwę pliku \"%1\"?",
+       RemoveTagsFromFiles: "usuń tagi z plików",
+       SetStylesError: "błąd: nie mogę zmienić \"%1\" na \"%2\.",
+       SaveThenClose: "Zapisz i zamknij",
+       SaveThenCloseQuestion: "Czy na pewno zapisać zmiany?",
+       SelectAll: "zaznacz wszystkie",
+       SelectNone: "wyczyść zaznaczenie",
+       Search: "Szukaj",
+       ShowPanel: "pokaż panel \"%1\"",
+       Tags: "tagi",
+       UnknownPanelState: "błąd: nieznany stan panelu.",
+       UrlNotValidLog: "błąd: adres URL musi się zaczynać od \"http:\"",
+       UnlockPanels: "odblokuj panele",
+       UrlNotValid: "błąd: adres URL musi się zaczynać od \"http:\"",
+       Upload: "Wyślij plik",
+       ViewImage: "podgląd obrazka",
+       WhatFilenameToCreateAs: "Podaj nazwę nowego pliku",
+       WhatMaximumSize: "Jaki ustawić maksymalny rozmiar?",
+       WhatIsTheNewTag: "Wpisz nowy tag.\nPoszczególne tagi oddziel przecinkami.",
+       WhichTagsDoYouWantToRemove: "Które tagi usunąć?\nPoszczególne tagi oddziel przecinkami.",
+       YouMustPlaceTheWildcard: "Musisz umieścić * w szablonie nazwy pliku",
+       YouNeedMoreThan: "Potrzebujesz więcej niż %1 * by utworzyć %2 pliki"
+       
+       ,
+       // New in 0.9
+       AllFiles: "wszystkie pliki",
+       AndNMore: "...i %1 więcej...",
+       Browse: "Przeglądaj...",
+       ExtractAfterUpload: "rozpakuj po wysłaniu",
+       NotAnImageOrImageDimensionsNotReported: "błąd: to nie jest obrazek, albo nie udało się rozpoznać rozmiarów obrazka",
+       PermissionDeniedCannotDeleteFile: "dostęp zabroniony: nie można usunąć pliku",
+       RenameTheDirectoryToWhat: "Na co zmienić nazwę katalogu '%1'?",
+       RenamedDirectoryAs: "Zmieniono nazwę z '%1' na '%2'",
+       TheFilenameShouldEndWithN: "nazwa pliku powinna kończyć się %1",
+       WhatFilenameDoYouWantToUse: "Jakiej nazwy pliku użyć?"
+
+,
+// New in 1.0
+ZipUpFiles: "zip up files",
+Cancel: "cancel"
+       , // new in 1.2
+       Icons                   : "icons", // used to select mode of file view
+       ListView                : "list-view", // used to select mode of file view
+       SendToCms               : "send to CMS", // close KFM and return the selected files to the CMS
+       CannotMoveDirectory     : "permission denied: cannot move directory",
+       LastModified            : "last modified", // part of File Details
+       ImageDimensions         : "image dimensions", // part of File Details
+       CouldNotMoveFiles       : "error: could not move file[s]",
+       CopyFiles               : "copy files", // when dragging files to a directory, two choices appear - "copy files" and "move files"
+       MoveFiles               : "move files",
+       AboutKfm                : "about KFM",
+       Errors                  : "Errors",
+       Ok                      : "OK" // as in "OK / Cancel"
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/pl.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/pl.php
new file mode 100644 (file)
index 0000000..680aa31
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *
+ * File Name: pl.php
+ *  Polish language file.
+ *
+ * File Authors:
+ *  kae@verens.com
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                => "\"%1\" already exists",
+       "errorInvalidID"               => "error: invalid ID",
+       "errorFileIDNotFound"          => "error: file id #%1 not found in database",
+       "bannedFilenameExtension"      => "banned extension in file name",
+       "cannotEditRestrictedExtension"=> "cannot edit \"%1\"\nrestricted by file extension",
+       "cannotMoveIntoSelf"           => "cannot move a directory into its own sub-directory",
+       "cannotRenameFromTo"           => "cannot rename \"%1\" to \"%2\"",
+       "CMSRefusesFileDelete"         => "CMS does not allow \"%1\" to be deleted",
+       "couldNotMoveDirectory"        => "could not move directory \"%1\" to \"%2\"",
+       "couldNotCreateFile"           => "could not write file \"%1\"",
+       "errorSettingFileContent"      => "error setting file content",
+       "failedCreateDirectoryCheck"   => "failed to create directory \"%1\"\ncheck filesystem permissions",
+       "failedRenameDirectory"        => "failed to rename directory",
+       "failedToSaveTmpFile"          => "failure to save tmp file \"%1\" to location \"%2\"",
+       "fileAlreadyExists"            => "a file of that name already exists",
+       "filesCopied"                  => "%1 files copied",
+       "illegalDirectoryName"         => "\"%1\" is an illegal directory name",
+       "illegalFileName"              => "\"%1\" is an illegal file name",
+       "illegalTargetDirectory"       => "illegal target directory \"%1\"",
+       "isNotWritable"                => "\"%1\" is not writable",
+       "missingFileInSelection"       => "missing file in selection",
+       "noDataForFileID"              => "no data for file id \"%1\"",
+       "noDataForDirectoryID"         => "no data for directory id \"%1\"",
+       "noNativeZipCommand"           => "no \"zip\" command found on server",
+       "permissionDeniedUpload"       => "permission denied for upload to this directory",
+       "permissionDeniedCreateDirectory"=>"permission denied: cannot create directory",
+       "permissionDeniedCreateFile"   => "permission denied: cannot create file",
+       "permissionDeniedDeleteDirectory"=>"permission denied: cannot delete directory",
+       "permissionDeniedDeleteFile"   => "permission denied: cannot delete file",
+       "permissionDeniedEditDirectory"=> "permission denied: cannot edit directory",
+       "permissionDeniedEditFile"     => "permission denied: cannot edit file",
+       "permissionDeniedMoveDirectory"=> "permission denied: cannot move directory",
+       "permissionDeniedMoveFile"     => "permission denied: cannot move file",
+       "permissionDeniedRename"       => "permission denied: cannot rename \"%1\"",
+       "permissionDeniedViewFile"     => "permission denied: cannot view file",
+       "searchResults"                => "search results",
+       # 1.2
+       "fileNotCreatedDirUnwritable"    => "\"%1\" could not be created. The directory is not writable",
+       "fileNotDeletedUnwritable"       => "\"%1\" cannot be removed. (file not writable)",
+       "fileNotMovableUnwritable"       => "\"%1\" cannot be moved. (file not writable)",
+       "permissionDeniedManipImage"     => "permission denied: cannot manipulate images",
+       "imageNotWritable"               => "image is not writable",
+       "failedGetFileObject"            => "failed to retrieve File object",
+       "failedGetDirectoryObject"       => "failed to retrieve Directory object",
+       "failedDeleteFile"               => "failed to delete file \"%1\"",
+       "failedMoveFile"                 => "failed to move file \"%1\"",
+       "failedWriteToFile"              => "failed write to file \"%1\"",
+       "failedDownloadFromUrl"        => "failed to download from URL \"%1\""
+       ,
+       "file saved"                     => "file saved",
+       "files deleted"                  => "%1 files deleted",
+       "errorZipContainsBannedFilename" => "error: zip contains a banned filename",
+       "error: filename not allowed"    => "error: filename not allowed",
+       "error: url must begin with http"=> "error: url must begin with http",
+       "UNKNOWN TAG"                    => "UNKNOWN TAG \"%1\"",
+       "error: unzip failed"            => "error: unzip failed"
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/ro.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/ro.js
new file mode 100755 (executable)
index 0000000..55d1780
--- /dev/null
@@ -0,0 +1,291 @@
+/*\r
+ * See ../license.txt for licensing\r
+ *\r
+ * File Name: ru.js\r
+ *     Romanian language file.\r
+ *\r
+ * File Authors:\r
+ *     \r
+ */\r
+\r
+kfm.lang=\r
+{\r
+Dir:\r
+       "ltr", // language direction\r
+ErrorPrefix:\r
+       "eroare: ",\r
+// what you see on the main page\r
+Directories:\r
+       "Mapele",\r
+CurrentWorkingDir:\r
+       "Mapă curenta: \"%1\"",\r
+Logs:\r
+       "Log-uri",\r
+FileUpload:\r
+       "Încărcarea fişierului",\r
+DirEmpty:\r
+       "fişierele n-au fost găsite în \"%1\"",\r
+\r
+// right click menu item directory\r
+// directory\r
+CreateSubDir:\r
+       "crearea submapei",\r
+DeleteDir:\r
+       "ştergerea mapei",\r
+RenameDir:\r
+       "schimbarea numelui mapei",\r
+\r
+//file\r
+DeleteFile:\r
+       "ştergerea fişierului",\r
+RenameFile:\r
+       "schimbarea numelui fişierului",\r
+RotateClockwise:\r
+       "rotaţie la dreaptă",\r
+RotateAntiClockwise:\r
+       "rotaţie la stângă",\r
+ResizeImage:\r
+       "schimbarea mărimii imaginii",\r
+ChangeCaption:\r
+       "schimbarea titlului",\r
+\r
+// create a file\r
+WhatFilenameToCreateAs:\r
+       "Fişierul va fi salvat ca?",\r
+AskIfOverwrite:\r
+       "Fişierul \"%1\" există. Rescrierea?",\r
+NoForwardslash:\r
+       "\nEste ilegal de utilizat '/' în numele fişierului",\r
+\r
+// messages management\r
+CreateDirMessage:\r
+       "Crearea submapei în \"%1\":",\r
+DelDirMessage:\r
+       "De şters mapă \"%1\"?",\r
+DelFileMessage:\r
+       "De şters fişierul \"%1\"",\r
+DelMultipleFilesMessage:\r
+       "De şters fişierele selectate?\n\n'",\r
+DownloadFileFromMessage:\r
+       "De unde se va încărca fişierul?",\r
+FileSavedAsMessage:\r
+       "Cum va fi salvat fişierul?",\r
+\r
+//resize file\r
+CurrentSize:\r
+       "Mărimea curentă: \"%1\" x \"%2\"\n",\r
+NewWidth:\r
+       "Laţime nouă?",\r
+NewWidthConfirmTxt:\r
+       "Laţime nouă: \"%1\"\n",\r
+NewHeight:\r
+       "Înalţime nouă?",\r
+NewHeightConfirmTxt:\r
+       "Înălţime nouă: \"%1\"\n\nIs this correct?",\r
+\r
+// log messages\r
+RenamedFile:\r
+       "schimbarea numelui fişierului din \"%1\" în \"%2\".",\r
+DirRefreshed:\r
+       "mapele au fost reînnoite.",\r
+FilesRefreshed:\r
+       "fişierele au fost reînnoite.",\r
+NotMoreThanOneFile:\r
+       "eroare: Dvs. nu puteţi să selectaţi decât un singur fişier odată",\r
+UnknownPanelState:\r
+       "eroare: starea panelului necunoscută.",\r
+//MissingDirWrapper:\r
+//     "error: missing directory wrapper: \"kfm_directories%1\".",\r
+SetStylesError:\r
+       "eroare: nu se poate de instalat \"%1\" în \"%2\.",\r
+NoPanel:\r
+       "eroare: panela \"%1\" nu există.",\r
+FileSelected:\r
+       "fişierul ales: \"%1\"",\r
+Log_ChangeCaption:\r
+       "schimbarea titlului din \"%1\" în \"%2\"",\r
+UrlNotValidLog:\r
+       "Eroare: URL trebui să înceapă cu \"http:\"",\r
+MovingFilesTo:\r
+       "mutarea fişierului din [\"%1\"] în \"%2\"",\r
+\r
+// error messages\r
+DirectoryNameExists:\r
+       "mapă cu această nume deja există.",\r
+FileNameNotAllowd:\r
+       "eroare: numele fişierului este blocată",\r
+CouldNotWriteFile:\r
+       "eroare: este imposibil de salvat fişierul \"%1\".",\r
+CouldNotRemoveDir:\r
+       "este imposibil de şters mapă.\npoate conţine fişiere activi",\r
+UrlNotValid:\r
+       "eroare: URL trebuie să înceapă cu \"http:\"",\r
+CouldNotDownloadFile:\r
+       "eroare: este imposibil de încărcat fişierul \"%1\".",\r
+FileTooLargeForThumb:\r
+       "eroare: \"%1\" este prea mare pentru crearea schiţei. Schimbaţi fişierul cu un alt cu o mărime mai mică",\r
+CouldntReadDir:\r
+       "eroare: este imposibil de citit mapă",\r
+CannotRenameFile:\r
+       "eroare: este imposibil de schimbat numele mapei \"%1\" în \"%2\"",\r
+FilenameAlreadyExists:\r
+       "eroare: fişierul cu acelaşi nume deja există",\r
+\r
+// new in 0.5\r
+EditTextFile:\r
+       "redactarea fişierului text",\r
+CloseWithoutSavingQuestion:\r
+       "OK pentru închiderea fără salvarea?",\r
+CloseWithoutSaving:\r
+       "Închiderea fără salvarea",\r
+SaveThenClose:\r
+       "Închide cu salvarea",\r
+SaveThenCloseQuestion:\r
+       "Salva schimbările?",\r
+\r
+// new in 0.6\r
+LockPanels:\r
+       "fixarea panelelor",\r
+UnlockPanels:\r
+       "scoaterea fixării panelelor",\r
+CreateEmptyFile:\r
+       "crearea fişierului gol",\r
+DownloadFileFromUrl:\r
+       "încărca din URL",\r
+DirectoryProperties:\r
+       "Caracteristicile mapei",\r
+SelectAll:\r
+       "sublinia tot",\r
+SelectNone:\r
+       "anula subliniare",\r
+InvertSelection:\r
+       "invertirea sublinierii",\r
+LoadingKFM:\r
+       "încărcare KFM",\r
+Name:\r
+       "nume",\r
+FileDetails:\r
+       "Informaţie despre fişier",\r
+Search:\r
+       "Căutare",\r
+IllegalDirectoryName:\r
+       "numele mapei este incorectă \"%1\"",\r
+RecursiveDeleteWarning:\r
+       "\"%1\" contine fişiere!\nOK pentru ştergerea mapei şi tuturor fişierelor din ea?\n*ATENŢIE* PROCESUL ESTE INREVERSIBIL!",\r
+RmdirFailed:\r
+       "imposibil de şters mapă \"%1\"",\r
+DirNotInDb:\r
+       "mapă lipseşte în baza de date",\r
+ShowPanel:\r
+       "de vizualizat panelă \"%1\"",\r
+ChangeCaption:\r
+       "Schimbarea Titlului",\r
+NewDirectory:\r
+       "Mapă nouă",\r
+Upload:\r
+       "Încărcare",\r
+NewCaptionIsThisCorrect:\r
+       "Titlu nou:\n%1\n\nEste Corect?",\r
+Close:\r
+       "închide",\r
+Loading:\r
+       "se încarcă",\r
+AreYouSureYouWantToCloseKFM:\r
+       "OK pentru închide fereastră cu KFM?",\r
+PleaseSelectFileBeforeRename:\r
+       "Alegeţi un fişier pentru schimbarea numelui",\r
+RenameOnlyOneFile:\r
+       "Puteţi să schimbaţi numele a unui fişier odată",\r
+RenameFileToWhat:\r
+       "De schimba numele fişierului \"%1\" în ...?",\r
+NoRestrictions:\r
+       "nu-s restricţii",\r
+Filename:\r
+       "numele fişierului",\r
+Maximise:\r
+       "extinderea",\r
+Minimise:\r
+       "reducerea",\r
+AllowedFileExtensions:\r
+       "extensiile acceptabile a fişierului",\r
+Filesize:\r
+       "mărimea fişierului",\r
+MoveDown:\r
+       "neglijarea",\r
+Mimetype:\r
+       "tipul mime",\r
+MoveUp:\r
+       "ridicarea",\r
+Restore:\r
+       "restituirea",\r
+Caption:\r
+       "titlu",\r
+CopyFromURL:\r
+       "A copia din URL",\r
+ExtractZippedFile:\r
+       "UNZIP",\r
+\r
+\r
+// new in 0.8\r
+ViewImage:\r
+       "vizionarea imaginii",\r
+ReturnThumbnailToOpener:\r
+       "utilizarea schiţei în loc de imagine încărcată",\r
+AddTagsToFiles:\r
+       "adăuga tag-uri la fişier(re)",\r
+RemoveTagsFromFiles:\r
+       "scoate tag-uri din fişier(re)",\r
+HowWouldYouLikeToRenameTheseFiles:\r
+       "Cum doriţi să schimbaţi numele acestor fişierelor?\n\nde exemplu: \"images-***.jpg\" va schimba numele în \"images-001.jpg\", \"images-002.jpg\", ...",\r
+YouMustPlaceTheWildcard:\r
+       "Dvs. trebuie să puneţi un semn de grupă (wildcard character) * undeva în şablonul numelui de fişier",\r
+YouNeedMoreThan:\r
+       "Dvs. trebuie să puneţi mai mult decât %1 * caractere pentru a crea %2 numele de fişieri",\r
+NoFilesSelected:\r
+       "nici un fişer a fost selectat",\r
+Tags:\r
+       "tag-uri",\r
+IfYouUseMultipleWildcards:\r
+       "Dacă Dvs. utilizaţi mai multe semne de grupă (wildcards) în şablonul numelui de fişier, ele trebuie să fie grupate împreună",\r
+NewCaption:\r
+       "Nou Titlu",\r
+WhatMaximumSize:\r
+       "Care mărimea maximă trebuie să fie returnată?",\r
+CommaSeparated:\r
+       "împărţite de virgulă",\r
+WhatIsTheNewTag:\r
+       "Care este tag-ul nou?\nPentru nişte tag-uri, utilizaţi virgulă pentru împarţire.",\r
+WhichTagsDoYouWantToRemove:\r
+       "Care tag-uri trebuie să fie scoase?\nPentru nişte tag-uri, utilizaţi virgulă pentru împarţire."\r
+\r
+,\r
+// New in 0.9\r
+AllFiles: "toate fişieri",\r
+AndNMore: "...şi %1 încă...",\r
+Browse: "Browse...",\r
+ExtractAfterUpload: "extragerea după primirea",\r
+NotAnImageOrImageDimensionsNotReported: "eroare: nu este o imagine, sau dimensiunile imaginii nu au fost stabilite",\r
+PermissionDeniedCannotDeleteFile: "accesul înterzis: fişierul nu poate fi şters",\r
+RenameTheDirectoryToWhat: "Modifica numele mapei din '%1' în...?",\r
+RenamedDirectoryAs: "Numele mapei a fost modificată din '%1' în '%2'",\r
+TheFilenameShouldEndWithN: "La sfârşitul numii de fişier trebuie să puneţi %1",\r
+WhatFilenameDoYouWantToUse: "Care numele de fişier doriţi să utilizaţi?"\r
+\r
+,\r
+// New in 1.0\r
+ZipUpFiles: "adăuga fişieri în arhivă",\r
+Cancel: "cancel"\r
+       , // new in 1.2\r
+       Icons                   : "iconiţe", // used to select mode of file view\r
+       ListView                : "lista", // used to select mode of file view\r
+       SendToCms               : "trimite la CMS", // close KFM and return the selected files to the CMS\r
+       CannotMoveDirectory     : "acces interzis: imposibil de mutat mapă",\r
+       LastModified            : "ultima dată schimbării", // part of File Details\r
+       ImageDimensions         : "dimensiunile imaginii", // part of File Details\r
+       CouldNotMoveFiles       : "eroare: imposibil de mutat fişier[e]",\r
+       CopyFiles               : "copia fişierele", // when dragging files to a directory, two choices appear - "copy files" and "move files"\r
+       MoveFiles               : "muta fişierele",\r
+       AboutKfm                : "despre KFM",\r
+       Errors                  : "Eroare",\r
+       Ok                      : "OK" // as in "OK / Cancel"\r
+}\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/ro.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/ro.php
new file mode 100644 (file)
index 0000000..ae39764
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *
+ * File Name: ro.php
+ *  Romanian language file.
+ *
+ * File Authors:
+ *  Andrei Suscov (info@kb.md)
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                => "\"%1\" deja există",
+       "errorInvalidID"               => "eraore: ID invalid",
+       "errorFileIDNotFound"          => "eroare: fişierul cu id #%1 nu a fost găsit în baza de date",
+       "bannedFilenameExtension"      => "extensie fişierului nu poate exista",
+       "cannotEditRestrictedExtension"=> "nu pot sa redactez \"%1\"\nrestriciţionată de extensie fişierului",
+       "cannotMoveIntoSelf"           => "mutarea mapei într-o submapă proprie este imposibilă",
+       "cannotRenameFromTo"           => "imposibil de schimbat numele din \"%1\" în \"%2\"",
+       "CMSRefusesFileDelete"         => "CMS nu dă voie să steargă \"%1\"",
+       "couldNotMoveDirectory"        => "imposibil de mutat mapă \"%1\" în \"%2\"",
+       "couldNotCreateFile"           => "imposibil de salvat fişierul \"%1\"",
+       "errorSettingFileContent"      => "eroare setarei conţinutului fişierului",
+       "failedCreateDirectoryCheck"   => "imposibil de creat mapă \"%1\"\nverificaţi permisiunele sistemului",
+       "failedRenameDirectory"        => "imposibil de schimbat numele mapei",
+       "failedToSaveTmpFile"          => "imposibil de salvat fişierul \"%1\" în \"%2\"",
+       "fileAlreadyExists"            => "fişierul cu aceasta nume deja există",
+       "filesCopied"                  => "s-a copiat %1 de fişieri",
+       "illegalDirectoryName"         => "\"%1\" este o nume ilegală pentru mapă",
+       "illegalFileName"              => "\"%1\" este o nume ilegală pentru fişier",
+       "illegalTargetDirectory"       => "mapă de destinaţie \"%1\" este ilegală",
+       "isNotWritable"                => "imposibil de salvat în \"%1\"",
+       "missingFileInSelection"       => "fişierul pierdut în selecţie",
+       "noDataForFileID"              => "nu-s datele pentru fişierul cu id \"%1\"",
+       "noDataForDirectoryID"         => "nu-s datele pentru mapa cu id \"%1\"",
+       "noNativeZipCommand"           => "comanda \"zip\" nu a fost găsită pe server",
+       "permissionDeniedUpload"       => "acces interzis pentru salvarea fişierului în mapa selectată",
+       "permissionDeniedCreateDirectory"=>"acces interzis: imposibil de creat mapă",
+       "permissionDeniedCreateFile"   => "acces interzis: imposibil de creat fişier",
+       "permissionDeniedDeleteDirectory"=>"acces interzis: imposibil de şters mapa",
+       "permissionDeniedDeleteFile"   => "acces interzis: imposibil de şters fişierul",
+       "permissionDeniedEditDirectory"=> "acces interzis: imposibil de redactat mapa",
+       "permissionDeniedEditFile"     => "acces interzis: imposibil de redactat fişierul",
+       "permissionDeniedMoveDirectory"=> "acces interzis: imposibil de mutat mapa",
+       "permissionDeniedMoveFile"     => "acces interzis: imposibil de mutat fişierul",
+       "permissionDeniedRename"       => "acces interzis: imposibil de schimbat numele ai \"%1\"",
+       "permissionDeniedViewFile"     => "acces interzis: imposibil de a vedea fişier",
+       "searchResults"                => "rezultatele căutării",
+       # 1.2
+       "fileNotCreatedDirUnwritable"    => "\"%1\" nu pot fi creat. Mapă este închisă pentru scriere.",
+       "fileNotDeletedUnwritable"       => "\"%1\" nu poate fi şters. (fişierul este închis pentru scriere)",
+       "fileNotMovableUnwritable"       => "\"%1\" nu poate fi mutat. (fişierul este închis pentru scriere)",
+       "permissionDeniedManipImage"     => "acces interzis: imposibil de manipulat cu imaginile",
+       "imageNotWritable"               => "imagine este închisă pentru scriere",
+       "failedGetFileObject"            => "imposibil de retras obiectul Fişierului",
+       "failedGetDirectoryObject"       => "imposibil de retras obiectul Mapei",
+       "failedDeleteFile"               => "imposibil de şters fişierul \"%1\"",
+       "failedMoveFile"                 => "imposibil de mutat fişierul \"%1\"",
+       "failedWriteToFile"              => "imposibil de salvat în fişierul \"%1\"",
+       "failedDownloadFromUrl"          => "imposibil de face download din URL \"%1\"",
+       "file saved"                     => "fişierul a fost salvat",
+       "files deleted"                  => "%1 fişierilor au fost şters",
+       "errorZipContainsBannedFilename" => "eroare: zip arhivarea conţine nume de fişier interzis",
+       "error: filename not allowed"    => "eroare: numele de fişier este ilegal",
+       "error: url must begin with http"=> "eroare: url-link trebuie să se înceapă cu http",
+       "UNKNOWN TAG"                    => "TAG-UL NECUNOSCUT \"%1\"",
+       "error: unzip failed"            => "eroare: unzip-dezarhivarea nu s-a reuşit"
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/ru.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/ru.js
new file mode 100755 (executable)
index 0000000..8af80f4
--- /dev/null
@@ -0,0 +1,292 @@
+/*\r
+ * See ../license.txt for licensing\r
+ *\r
+ * File Name: ru.js\r
+ *     Russian language file.\r
+ *\r
+ * File Authors:\r
+ *     \r
+ */\r
+\r
+kfm.lang=\r
+{\r
+Dir:\r
+       "ltr", // language direction\r
+ErrorPrefix:\r
+       "ошибка: ",\r
+// what you see on the main page\r
+Directories:\r
+       "Каталоги",\r
+CurrentWorkingDir:\r
+       "Текущий рабочий каталог: \"%1\"",\r
+Logs:\r
+       "Логи",\r
+FileUpload:\r
+       "Загрузка файла",\r
+DirEmpty:\r
+       "не найдены файлы в \"%1\"",\r
+\r
+// right click menu item directory\r
+// directory\r
+CreateSubDir:\r
+       "создать подкаталог",\r
+DeleteDir:\r
+       "удалить",\r
+RenameDir:\r
+       "переименовать",\r
+\r
+//file\r
+DeleteFile:\r
+       "удалить",\r
+RenameFile:\r
+       "переименовать",\r
+RotateClockwise:\r
+       "повернуть вправо",\r
+RotateAntiClockwise:\r
+       "повернуть влево",\r
+ResizeImage:\r
+       "изменить размер картинки",\r
+ChangeCaption:\r
+       "изменить подпись",\r
+\r
+// create a file\r
+WhatFilenameToCreateAs:\r
+       "Файл будет сохранен, как?",\r
+AskIfOverwrite:\r
+       "Файл \"%1\" существует. Перезаписать?",\r
+NoForwardslash:\r
+       "\nНельзя использовать '/' в имени файла",\r
+\r
+// messages management\r
+CreateDirMessage:\r
+       "Создать подкаталог в \"%1\":",\r
+DelDirMessage:\r
+       "Вы уверены, что хотите удалить каталог \"%1\"?",\r
+DelFileMessage:\r
+       "Вы уверены, что хотите удалить файл \"%1\"",\r
+DelMultipleFilesMessage:\r
+       "Вы уверены, что хотите удалить перечисленные файлы?\n\n'",\r
+DownloadFileFromMessage:\r
+       "Откуда закачивать файл?",\r
+FileSavedAsMessage:\r
+       "Как будет сохранен файл?",\r
+\r
+//resize file\r
+CurrentSize:\r
+       "Текущий размер: \"%1\" x \"%2\"\n",\r
+NewWidth:\r
+       "Новая ширина?",\r
+NewWidthConfirmTxt:\r
+       "Новая ширина: \"%1\"\n",\r
+NewHeight:\r
+       "Новая высота?",\r
+NewHeightConfirmTxt:\r
+       "Новая высота: \"%1\"\n\nIs this correct?",\r
+\r
+// log messages\r
+RenamedFile:\r
+       "переименование файла \"%1\" в \"%2\".",\r
+DirRefreshed:\r
+       "каталоги обновлены.",\r
+FilesRefreshed:\r
+       "файлы обновлены.",\r
+NotMoreThanOneFile:\r
+       "ошибка: нельзя выбрать больше одного файла за раз",\r
+UnknownPanelState:\r
+       "ошибка: неизвестное состояние панели.",\r
+//MissingDirWrapper:\r
+//     "error: missing directory wrapper: \"kfm_directories%1\".",\r
+SetStylesError:\r
+       "ошибка: нельзя установить \"%1\" в \"%2\.",\r
+NoPanel:\r
+       "ошибка: панель \"%1\" не существует.",\r
+FileSelected:\r
+       "выбран файл: \"%1\"",\r
+Log_ChangeCaption:\r
+       "изменение подписи с \"%1\" на \"%2\"",\r
+UrlNotValidLog:\r
+       "Ошибка: URL должен начинаться с \"http:\"",\r
+MovingFilesTo:\r
+       "перемещение файла [\"%1\"] в \"%2\"",\r
+\r
+// error messages\r
+DirectoryNameExists:\r
+       "каталог с таким именем уже существует.",\r
+FileNameNotAllowd:\r
+       "ошибка: имя файла запрещено",\r
+CouldNotWriteFile:\r
+       "ошибка: нельзя записать файл \"%1\".",\r
+CouldNotRemoveDir:\r
+       "нельзя удалить каталог.\nвозможно он не пуст",\r
+UrlNotValid:\r
+       "ошибка: URL должен начинаться с \"http:\"",\r
+CouldNotDownloadFile:\r
+       "ошибка: невозможно загрузить файл \"%1\".",\r
+FileTooLargeForThumb:\r
+       "ошибка: \"%1\" слишком большой чтобы сделать эскиз. Замените файл на меньший по размеру",\r
+CouldntReadDir:\r
+       "ошибка: невозможно прочитать каталог",\r
+CannotRenameFile:\r
+       "ошибка: нельзя переименовать \"%1\" в \"%2\"",\r
+FilenameAlreadyExists:\r
+       "ошибка: файл с таким именем уже существует",\r
+\r
+// new in 0.5\r
+EditTextFile:\r
+       "редактирование текстового файла",\r
+CloseWithoutSavingQuestion:\r
+       "Уверены, что хотите закрыть без сохранения?",\r
+CloseWithoutSaving:\r
+       "Закрыть без сохранения",\r
+SaveThenClose:\r
+       "Сохранять, при закрытии",\r
+SaveThenCloseQuestion:\r
+       "Сохранить изменения?",\r
+\r
+// new in 0.6\r
+LockPanels:\r
+       "закрепить панели",\r
+UnlockPanels:\r
+       "снять закрепление панелей",\r
+CreateEmptyFile:\r
+       "создать пустой файл",\r
+DownloadFileFromUrl:\r
+       "загрузить с URL",\r
+DirectoryProperties:\r
+       "Свойства каталога",\r
+SelectAll:\r
+       "выделить все",\r
+SelectNone:\r
+       "снять выделение",\r
+InvertSelection:\r
+       "инвертировать выделение",\r
+LoadingKFM:\r
+       "загрузка KFM",\r
+Name:\r
+       "имя",\r
+FileDetails:\r
+       "Информация о файле",\r
+Search:\r
+       "Поиск",\r
+IllegalDirectoryName:\r
+       "некорректное имя папки \"%1\"",\r
+RecursiveDeleteWarning:\r
+       "\"%1\" не пустая\nВы уверены, что хотите стереть папку и все содержимое?\n*ВНИМАНИЕ* ПРОЦЕСС НЕОБРАТИМ!",\r
+RmdirFailed:\r
+       "невозможно удалить папку \"%1\"",\r
+DirNotInDb:\r
+       "папка отсутствует в базе данных",\r
+ShowPanel:\r
+       "показать панель \"%1\"",\r
+ChangeCaption:\r
+       "Изменить Подпись",\r
+NewDirectory:\r
+       "Новая папка",\r
+Upload:\r
+       "Загрузить",\r
+NewCaptionIsThisCorrect:\r
+       "Новая Подпись:\n%1\n\nЭто верно?",\r
+Close:\r
+       "закрыть",\r
+Loading:\r
+       "загружается",\r
+AreYouSureYouWantToCloseKFM:\r
+       "Вы уверены что хотие закрыть окно с KFM?",\r
+PleaseSelectFileBeforeRename:\r
+       "Пожалуйста, выберите файл, перед тем как его переименовать",\r
+RenameOnlyOneFile:\r
+       "Вы можете переименовать только один файл за одну операцию",\r
+RenameFileToWhat:\r
+       "Переименовать файл \"%1\" в ...?",\r
+NoRestrictions:\r
+       "нет ограничений",\r
+Filename:\r
+       "имя файла",\r
+Maximise:\r
+       "увеличить",\r
+Minimise:\r
+       "уменьшить",\r
+AllowedFileExtensions:\r
+       "допустимые расширения файла",\r
+Filesize:\r
+       "размер файла",\r
+MoveDown:\r
+       "опустить вниз",\r
+Mimetype:\r
+       "тип mime",\r
+MoveUp:\r
+       "поднять наверх",\r
+Restore:\r
+       "вернуть назад",\r
+Caption:\r
+       "подпись",\r
+CopyFromURL:\r
+       "Скопировать из URL",\r
+ExtractZippedFile:\r
+       "Распаковать файл ZIP",\r
+\r
+\r
+\r
+// new in 0.8\r
+ViewImage:\r
+       "просмотреть изображение",\r
+ReturnThumbnailToOpener:\r
+       "использовать для показа эскиз вместо рисунка",\r
+AddTagsToFiles:\r
+       "добавить тэги к файлу(файлам)",\r
+RemoveTagsFromFiles:\r
+       "убрать тэги с файла(файлов)",\r
+HowWouldYouLikeToRenameTheseFiles:\r
+       "Как бы вы хотели переименовать эти файлы?\n\nнапример: \"images-***.jpg\" переименует файлы в \"images-001.jpg\", \"images-002.jpg\", ...",\r
+YouMustPlaceTheWildcard:\r
+       "Вы должны поместить групповой символ * где-то в шаблоне имени файла",\r
+YouNeedMoreThan:\r
+       "Вам надо более чем %1 * знаков чтобы создать %2 имен файлов",\r
+NoFilesSelected:\r
+       "не выбрано ни одного файла",\r
+Tags:\r
+       "тэги",\r
+IfYouUseMultipleWildcards:\r
+       "Если вы используете несколько групповых символов в шаблоне имени файла, они должны быть сгруппированы вместе",\r
+NewCaption:\r
+       "Новая подпись",\r
+WhatMaximumSize:\r
+       "Какой маскимальный размер должен быть возвращен?",\r
+CommaSeparated:\r
+       "разделенные запятой",\r
+WhatIsTheNewTag:\r
+       "Какой новый тэг?\nПри написании нескольких тэгов, разделяйте их запятой.",\r
+WhichTagsDoYouWantToRemove:\r
+       "Какие тэги вы хотите убрать?\nПри написании нескольких тэгов, разделяйте их запятой."\r
+\r
+,\r
+// New in 0.9\r
+AllFiles: "все файлы",\r
+AndNMore: "...и %1 еще...",\r
+Browse: "Обзор...",\r
+ExtractAfterUpload: "распаковать после загрузки",\r
+NotAnImageOrImageDimensionsNotReported: "ошибка: не изображение, или размеры изображения не заданы",\r
+PermissionDeniedCannotDeleteFile: "доступ запрещен: невозможно удалить файл",\r
+RenameTheDirectoryToWhat: "Переименовать каталог '%1' в...?",\r
+RenamedDirectoryAs: "Переименован '%1' в '%2'",\r
+TheFilenameShouldEndWithN: " Имя файла должно заканчиваться на %1",\r
+WhatFilenameDoYouWantToUse: "Какое имя файла вы хотите использовать?"\r
+\r
+,\r
+// New in 1.0\r
+ZipUpFiles: "заархивировать файлы",\r
+Cancel: "отменить"\r
+       , // new in 1.2\r
+       Icons                   : "иконки", // used to select mode of file view\r
+       ListView                : "список", // used to select mode of file view\r
+       SendToCms               : "послать в CMS", // close KFM and return the selected files to the CMS\r
+       CannotMoveDirectory     : "доступ запрещен: невозможно переместить папку",\r
+       LastModified            : "последний раз изменен", // part of File Details\r
+       ImageDimensions         : "размеры изображения", // part of File Details\r
+       CouldNotMoveFiles       : "ошибка: невозможно переместить файл[ы]",\r
+       CopyFiles               : "скопировать файлы", // when dragging files to a directory, two choices appear - "copy files" and "move files"\r
+       MoveFiles               : "переместить файлы",\r
+       AboutKfm                : "о KFM",\r
+       Errors                  : "Ошибки",\r
+       Ok                      : "OK" // as in "OK / Cancel"\r
+}\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/ru.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/ru.php
new file mode 100644 (file)
index 0000000..42ef865
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *
+ * File Name: ru.php
+ *  Russian language file.
+ *
+ * File Authors:
+ *  Andrei Suscov (info@kb.md)
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                => "\"%1\" уже существует",
+       "errorInvalidID"               => "ошибка: несуществующий ID",
+       "errorFileIDNotFound"          => "ошибка: файл с id #%1 не найден в базе данных",
+       "bannedFilenameExtension"      => "это расширение не может быть использовано",
+       "cannotEditRestrictedExtension"=> "невозможно отредактировать \"%1\"\nзапрещено расширением файла",
+       "cannotMoveIntoSelf"           => "невозможно перенести директорию в собственную поддиректорию",
+       "cannotRenameFromTo"           => "невозможно переименовать \"%1\" в \"%2\"",
+       "CMSRefusesFileDelete"         => "CMS не позволяет удалить \"%1\"",
+       "couldNotMoveDirectory"        => "невозможно перенести директорию \"%1\" в \"%2\"",
+       "couldNotCreateFile"           => "невозможно записать файл \"%1\"",
+       "errorSettingFileContent"      => "ошибка при задании контента файла",
+       "failedCreateDirectoryCheck"   => "ошибка при создании директории \"%1\"\nпроверьте уровень доступа системы",
+       "failedRenameDirectory"        => "невозможно переименовать директорию",
+       "failedToSaveTmpFile"          => "невозможно сохранить временный файл \"%1\" в \"%2\"",
+       "fileAlreadyExists"            => "файл с таким именем уже существует",
+       "filesCopied"                  => "скопировано %1 файлов",
+       "illegalDirectoryName"         => "\"%1\" - неправильное имя папки",
+       "illegalFileName"              => "\"%1\" - неправильное имя файла",
+       "illegalTargetDirectory"       => "неправильная папка назначения \"%1\"",
+       "isNotWritable"                => "невозможно записать в \"%1\"",
+       "missingFileInSelection"       => "отсутствует файл в выборке",
+       "noDataForFileID"              => "нет данных для файла с id \"%1\"",
+       "noDataForDirectoryID"         => "нет данных для папки с id \"%1\"",
+       "noNativeZipCommand"           => "\"zip\" комманда не найдена на сервере",
+       "permissionDeniedUpload"       => "доступ запрещен для загрузки в эту папку",
+       "permissionDeniedCreateDirectory"=>"доступ запрещен: невозможно создать папку",
+       "permissionDeniedCreateFile"   => "доступ запрещен: невозможно создать файл",
+       "permissionDeniedDeleteDirectory"=>"доступ запрещен: невозможно удалить папку",
+       "permissionDeniedDeleteFile"   => "доступ запрещен: вевозможно удалить файл",
+       "permissionDeniedEditDirectory"=> "доступ запрещен: невозможно отредактировать папку",
+       "permissionDeniedEditFile"     => "доступ запрещен: невозможно отредактировать файл",
+       "permissionDeniedMoveDirectory"=> "доступ запрещен: невозможно перенести папку",
+       "permissionDeniedMoveFile"     => "доступ запрещен: невозможно перенести файл",
+       "permissionDeniedRename"       => "доступ запрещен: невозможно переименовать \"%1\"",
+       "permissionDeniedViewFile"     => "доступ запрещен: невозможно просмотреть файл",
+       "searchResults"                => "результаты поиска",
+       # 1.2
+       "fileNotCreatedDirUnwritable"    => "\"%1\" не может быть создан. Папка защищена от записи",
+       "fileNotDeletedUnwritable"       => "\"%1\" не может быть удален. (файл защищен от записи)",
+       "fileNotMovableUnwritable"       => "\"%1\" не может быть перемещен. (файл защищен от записи)",
+       "permissionDeniedManipImage"     => "доступ закрыт: невозможно работать с изображениями",
+       "imageNotWritable"               => "изображение защищено от записи",
+       "failedGetFileObject"            => "невозможно достать объект Файла",
+       "failedGetDirectoryObject"       => "невозможно достать объект Папки",
+       "failedDeleteFile"               => "невозможно удалить файл \"%1\"",
+       "failedMoveFile"                 => "невозможно переместить файл \"%1\"",
+       "failedWriteToFile"              => "невозможно записать в файл \"%1\"",
+       "failedDownloadFromUrl"          => "невозможно закачать из URL \"%1\"",
+       "file saved"                     => "файл сохранен",
+       "files deleted"                  => "%1 файлов стерто",
+       "errorZipContainsBannedFilename" => "ошибка: архив zip содержит запрещенное имя файла",
+       "error: filename not allowed"    => "ошибка: данное имя файла запрещено",
+       "error: url must begin with http"=> "ошибка: url-ссылка должна начинаться с http",
+       "UNKNOWN TAG"                    => "НЕИЗВЕСТНЫЙ ТАГ \"%1\"",
+       "error: unzip failed"            => "ошибка: дезархивация невозможна"
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/sv.js b/ipf/admin/media/tiny_mce/plugins/kfm/lang/sv.js
new file mode 100644 (file)
index 0000000..0ab0c15
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *     http                    ://kfm.verens.com/
+ *
+ * File Name: sv.js
+ *     Swedish language file.
+ *
+ * File Authors:
+ *     maccer83@gmail.com
+ */
+
+kfm.lang={
+       AddTagsToFiles          : "lägg till taggar till fil(er)",
+       AllFiles                : "alla filer",
+       AllowedFileExtensions   : "tillåtna filnamnstillägg",
+       AndNMore                : "...och %1 till...",
+       AreYouSureYouWantToCloseKFM: "Är du säker på att du vill stänga KFM-fönstret?",
+       AskIfOverwrite          : "File \"%1\" finns redan. Vill du skriva över den?",
+       Browse                  : "Välj fil...",
+       Cancel                  : "avbryt",
+       CouldNotWriteFile       : "fel: kunde inte skriva filen \"%1\".",
+       CreateSubDir            : "skapa undermapp",
+       CurrentWorkingDir       : "Nuvarande arbetskatalog: \"%1\"",
+       CouldNotRemoveDir       : "kan inte radera mappen.\nvar vänlig kontrollera att mappen är tom",
+       CouldNotDownloadFile    : "fel: kunde inte ladda ner fil \"%1\".",
+       CouldntReadDir          : "fel: kunde inte läsa mapp",
+       CreateEmptyFile         : "skapa tom fil",
+       CloseWithoutSavingQuestion: "Är du säker på att du vill stänga utan att spara?",
+       CloseWithoutSaving      : "Stäng utan att spara",
+       CannotRenameFile        : "fel: kan inte byta namn på \"%1\" till \"%2\"",
+       ChangeCaption           : "byt bildtext",
+       CreateDirMessage        : "Skapa en undermapp till \"%1\":",
+       CurrentSize             : "Nuvarande storlek: \"%1\" x \"%2\"\n",
+       Close                   : "stäng",
+       Caption                 : "bildtext",
+       CommaSeparated          : "komma-separerad",
+       CopyFromURL             : "Hämta fil från URL",
+       Dir                     : "ltr", // language direction
+       Directories             : "Mappar",
+       DeleteFile              : "radera",
+       DirEmpty                : "inga filer funna i \"%1\"",
+       DeleteDir               : "radera",
+       DelDirMessage           : "Är du säker på att du vill radera mappen \"%1\"?",
+       DelFileMessage          : "Är du säker på att du vill radera filen \"%1\"?",
+       DelMultipleFilesMessage : "Är du säker på att du vill radera följande filer?\n\n",
+       DownloadFileFromMessage : "Varifrån ska filen laddas ner?",
+       DirRefreshed            : "mappar uppdaterade.",
+       DirectoryNameExists     : "en mapp med detta namn existerar redan.",
+       DownloadFileFromUrl     : "ladda ner fil från URL",
+       DirectoryProperties     : "Mappinformation",
+       DirNotInDb              : "mapp saknas i databas",
+       ErrorPrefix             : "fel: ",
+       EditTextFile            : "redigera textfil",
+       ExtractAfterUpload      : "packa upp efter uppladdning",
+       ExtractZippedFile       : "Packa upp zippad fil",
+       FileSavedAsMessage      : "Vad ska filen sparas som?",
+       FileUpload              : "Filuppladdning",
+       FilesRefreshed          : "filer uppdaterade.",
+       FileSelected            : "valda filer: \"%1\"",
+       FileNameNotAllowd       : "fel: otillåtet filnamn",
+       FileTooLargeForThumb    : "fel: \"%1\" är så stor att det inte går att skapa en miniatyrbild. Var vänlig ersätt filen med en mindre variant.",
+       FilenameAlreadyExists   : "fel: en fil med detta namn existerar redan",
+       FileDetails             : "Filinformation",
+       Filename                : "filnamn",
+       Filesize                : "filstorlek",
+       HowWouldYouLikeToRenameTheseFiles: "Hur önskar du byta namn på filerna?\n\nexempel: \"bild-***.jpg\" byter namn på filerna till \"bild-001.jpg\", \"bild-002.jpg\", ...",
+       InvertSelection         : "invertera markering",
+       IfYouUseMultipleWildcards: "Om du använder flera jokertecken i filnamnsmallen måste dessa vara grupperade.",
+       IllegalDirectoryName    : "otillåtet namn på mapp \"%1\"",
+       LockPanels              : "lås paneler",
+       Loading                 : "laddar",
+       LoadingKFM              : "laddar KFM",
+       Log_ChangeCaption: "byter bildtext på \"%1\" till \"%2\"",
+       Logs                    : "Loggar",
+       MovingFilesTo           : "flyttar filerna [\"%1\"] till \"%2\"",
+       Maximise                : "maximera",
+       Minimise                : "minimera",
+       MoveDown                : "flytta ner",
+       Mimetype                : "mime-typ",
+       MoveUp                  : "flytta upp",
+       NewCaptionIsThisCorrect : "Ny bildtext:\n%1\n\nÄr detta korrekt?",
+       Name                    : "namn",
+       NewDirectory            : "Ny mapp",
+       NoRestrictions          : "inga restriktioner",
+       NoForwardslash          : "\nDu får inte använda '/' i filnamnet",
+       NewWidth                : "Ange ny bredd:",
+       NoPanel                 : "fel: panel \"%1\" existerar inte.",
+       NotAnImageOrImageDimensionsNotReported: "fel: ej en bild, eller bildmått saknas",
+       NewCaption              : "Ny bildtext",
+       NewWidthConfirmTxt      : "Ny bredd: \"%1\"\n",
+       NewHeight               : "Ange ny höjd:",
+       NewHeightConfirmTxt     : "Ny höjd: \"%1\"\n\nÄr detta korrekt?",
+       NotMoreThanOneFile      : "fel: du kan bara välja en fil i taget",
+       NoFilesSelected         : "inga filer valda",
+       PermissionDeniedCannotDeleteFile: "otillräcklig behörighet: kan inte radera fil",
+       PleaseSelectFileBeforeRename: "Var vänlig välj en fil innan du försöker byta namn på den",
+       RenameDir               : "byt namn",
+       RenameFile              : "byt namn",
+       RotateClockwise         : "rotera medurs",
+       RotateAntiClockwise     : "rotera moturs",
+       ResizeImage             : "ändra storlek på bild",
+       RenamedFile             : "byter namn på fil \"%1\" till \"%2\".",
+       Restore                 : "återställ",
+       ReturnThumbnailToOpener : "returnera miniatyrbild till editorn",
+       RenameOnlyOneFile       : "Du kan endast byta namn på en fil i taget",
+       RecursiveDeleteWarning  : "\"%1\" är inte tom\nÄr du säker på att du vill radera den och allt dess innehåll?\n*VARNING* DETTA KAN EJ ÅNGRAS",
+       RmdirFailed             : "kunde inte radera mapp \"%1\"",
+       RenamedDirectoryAs      : "Bytte namn på '%1' till '%2'",
+       RenameFileToWhat        : "Ange nytt namn för filen \"%1\":",
+       RenameTheDirectoryToWhat: "Ange nytt namn för mappen '%1':",
+       RemoveTagsFromFiles     : "ta bort taggar från fil(er)",
+       SetStylesError          : "fel: kan inte sätta \"%1\" till \"%2\.",
+       SaveThenClose           : "Spara och stäng",
+       SaveThenCloseQuestion   : "Är du säker på att du vill spara dina ändringar?",
+       SelectAll               : "markera allt",
+       SelectNone              : "markera inget",
+       Search                  : "Sök",
+       ShowPanel               : "visa panel \"%1\"",
+       Tags                    : "taggar",
+       TheFilenameShouldEndWithN: "Filnamet bör sluta med %1",
+       UnknownPanelState       : "fel: okänt tillstånd på panelen.",
+       UrlNotValidLog          : "fel: URL:en måste börja med \"http:\"",
+       UnlockPanels            : "lås upp paneler",
+       UrlNotValid             : "fel: URL:en måste börja med \"http:\"",
+       Upload                  : "Ladda upp fil",
+       ViewImage               : "visa bild",
+       WhatFilenameDoYouWantToUse: "Vilket filnamn vill du använda?",
+       WhatFilenameToCreateAs  : "Ange namn för filen som ska skapas:",
+       WhatMaximumSize         : "Ange maximal storlek som ska returneras:",
+       WhatIsTheNewTag         : "Ange ny tagg:\n\nDu kan ange flera taggar samtidigt\ngenom att separera dem med komma.",
+       WhichTagsDoYouWantToRemove: "Ange tagg som ska tas bort:\n\nDu kan ange flera taggar samtidigt\ngenom att separera dem med komma.",
+       YouMustPlaceTheWildcard : "Du måste placera jokertecknet * någonstans i filnamnsmallen",
+       YouNeedMoreThan         : "Du måste ange fler än %1 * tecken för att skapa %2 filnamn",
+       ZipUpFiles              : "packa upp filer"
+       , // new in 1.2
+       Icons                   : "ikoner", // used to select mode of file view
+       ListView                : "lista", // used to select mode of file view
+       SendToCms               : "skicka till CMS", // close KFM and return the selected files to the CMS
+       CannotMoveDirectory     : "otillräcklig behörighet: kan inte flytta mapp",
+       LastModified            : "senast ändrad", // part of File Details
+       ImageDimensions         : "bildmått", // part of File Details
+       CouldNotMoveFiles       : "fel: cunde inte flytta fil[er]",
+       CopyFiles               : "kopiera filer", // when dragging files to a directory, two choices appear - "copy files" and "move files"
+       MoveFiles               : "flytta files",
+       AboutKfm                : "om KFM",
+       Errors                  : "Fel",
+       Ok                      : "OK" // as in "OK / Cancel"
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/lang/sv.php b/ipf/admin/media/tiny_mce/plugins/kfm/lang/sv.php
new file mode 100644 (file)
index 0000000..75054eb
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/*
+ * See ../license.txt for licensing
+ *
+ * For further information visit:
+ *  http://kfm.verens.com/
+ *
+ * File Name: sv.php
+ *  Swedish language file.
+ *
+ * File Authors:
+ *  maccer83@gmail.com
+ */
+
+$kfm_langStrings=array(
+       "alreadyExists"                  => "\"%1\" finns redan",
+       "errorInvalidID"                 => "fel: felaktigt ID",
+       "errorFileIDNotFound"            => "fel: fil-id #%1 hittades inte i databasen",
+       "bannedFilenameExtension"        => "förbjudet filnamnstillägg",
+       "cannotEditRestrictedExtension"  => "kan inte redigera \"%1\"\nhindrat p.g.a. filnamnstillägg",
+       "cannotMoveIntoSelf"             => "kan inte flytta en mapp till en av sin egna undermappar",
+       "cannotRenameFromTo"             => "kan inte byta namn på \"%1\" till \"%2\"",
+       "CMSRefusesFileDelete"           => "CMS:et tillåter inte att \"%1\" raderas",
+       "couldNotMoveDirectory"          => "kunde inte flytta mappen \"%1\" till \"%2\"",
+       "couldNotCreateFile"             => "kunde inte skriva filen \"%1\"",
+       "errorSettingFileContent"        => "fel vid skapande av filinnehåll",
+       "failedCreateDirectoryCheck"     => "kunde inte skapa mapp \"%1\"\nkontrollera filsystemets rättigheter",
+       "failedRenameDirectory"          => "kunde inte byta namn på mapp",
+       "failedToSaveTmpFile"            => "kunde inte spara tmp-fil \"%1\" till platsen \"%2\"",
+       "fileAlreadyExists"              => "en fil med detta namn finns redan",
+       "filesCopied"                    => "%1 filer kopierade",
+       "illegalDirectoryName"           => "\"%1\" är ett otillåtet mappnamn",
+       "illegalFileName"                => "\"%1\" är ett otillåtet filnamn",
+       "illegalTargetDirectory"         => "otillåten målmapp \"%1\"",
+       "isNotWritable"                  => "\"%1\" är inte skrivbar",
+       "missingFileInSelection"         => "saknad fil i markering",
+       "noDataForFileID"                => "ingen information för fil-id \"%1\"",
+       "noDataForDirectoryID"           => "ingen information för mapp-id \"%1\"",
+       "noNativeZipCommand"             => "\"zip\"-kommandot kan ej hittas på servern",
+       "permissionDeniedUpload"         => "rättigheter saknas för att ladda upp till denna mapp",
+       "permissionDeniedCreateDirectory"=> "otillräckliga rättigheter: kan inte skapa mapp",
+       "permissionDeniedCreateFile"     => "otillräckliga rättigheter: kan inte skapa fil",
+       "permissionDeniedDeleteDirectory"=> "otillräckliga rättigheter: kan inte radera mapp",
+       "permissionDeniedDeleteFile"     => "otillräckliga rättigheter: kan inte radera fil",
+       "permissionDeniedEditDirectory"  => "otillräckliga rättigheter: kan inte redigera mapp",
+       "permissionDeniedEditFile"       => "otillräckliga rättigheter: kan inte redigera fil",
+       "permissionDeniedMoveDirectory"  => "otillräckliga rättigheter: kan inte flytta mapp",
+       "permissionDeniedMoveFile"       => "otillräckliga rättigheter: kan inte flytta fil",
+       "permissionDeniedRename"         => "otillräckliga rättigheter: kan inte byta namn på \"%1\"",
+       "permissionDeniedViewFile"       => "otillräckliga rättigheter: kan inte visa filen",
+       "searchResults"                  => "sökresultat",
+       # 1.2
+       "fileNotCreatedDirUnwritable"    => "fel: \"%1\" kunde inte skapas. Mappen är inte skrivbar",
+       "fileNotDeletedUnwritable"       => "fel: \"%1\" kunde inte raderas. (filen är inte skrivbar)",
+       "fileNotMovableUnwritable"       => "fel: \"%1\" kan inte flyttas. (filen är inte skrivbar)",
+       "permissionDeniedManipImage"     => "fel: otillräckliga rättigheter: kan inte manipulera bilder",
+       "imageNotWritable"               => "fel: bilden är inte skrivbar",
+       "failedGetFileObject"            => "fel: kunde inte hämta File-objektet",
+       "failedGetDirectoryObject"       => "fel: kunde inte hämta Directory-objektet",
+       "failedDeleteFile"               => "fel: kunde inte radera fil \"%1\"",
+       "failedMoveFile"                 => "fel: kunde inte flytta fil \"%1\"",
+       "failedWriteToFile"              => "fel: kunde inte skriva till fil \"%1\"",
+       "failedDownloadFromUrl"          => "fel: kunde inte ladda ner från URL \"%1\""
+       ,
+       "file saved"                     => "fil sparad",
+       "files deleted"                  => "%1 filer raderade",
+       "errorZipContainsBannedFilename" => "fel: zip-filen innehåller en fil med otillåtet filnamn",
+       "fel: filename not allowed"    => "fel: filnamn inte tillåtet",
+       "fel: url must begin with http"=> "fel: URL:en måste börja med http",
+       "UNKNOWN TAG"                    => "OKÄND TAGG \"%1\"",
+       "fel: unzip failed"            => "fel: uppackningen misslyckades"
+);
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/maintenance.php b/ipf/admin/media/tiny_mce/plugins/kfm/maintenance.php
new file mode 100644 (file)
index 0000000..a744e1e
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+/**
+ * KFM - Kae's File Manager - database maintenance
+ *
+ * @category None
+ * @package  None
+ * @author   Benjamin ter Kuile <bterkuile@gmail.com>
+ * @license  docs/license.txt for licensing
+ * @link     http://kfm.verens.com/
+ */
+require_once 'initialise.php';
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+<head>
+<title>KFM-maintenance</title>
+<link rel="stylesheet" href="themes/<?php echo $kfm_theme; ?>/prompt.css" />
+<script type="text/javascript" src="j/jquery/jquery-1.2.2.pack.js"></script>
+<script type="text/javascript" src="j/jquery/jquery.impromptu.js"></script>
+<script type="text/javascript">
+       var $j = jQuery.noConflict();
+       $j(document).ready(function(){
+               $j.prompt($j('#maintenance_complete_html').html(),{
+                       buttons:{'Show messages':false,'Go to the file manager':true},
+                       callback:function(v,m){
+                               if(v)window.location='index.php';
+                       }
+               });
+       });
+</script>
+<style type="text/css">
+body{
+       background-color:#eeeeee;
+}
+</style>
+</head>
+<body>
+<div id="maintenance_messages">
+<?php
+//Ghost file deletion
+$kfmdb->query('DELETE FROM '.$kfm_db_prefix.'_files WHERE directory=0');
+?>
+<p>Maintenance done. <a href="index.php">Return to the filemanager</a></p>
+</div>
+<div id="maintenance_complete_html" style="display:none;">
+<h2>Maintenance complete</h2>
+</div>
+</body>
+</html>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/codepress.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/codepress.css
new file mode 100755 (executable)
index 0000000..2186820
--- /dev/null
@@ -0,0 +1,21 @@
+body {\r
+       margin-top:13px;\r
+       _margin-top:14px;\r
+       background:white;\r
+       margin-left:32px;\r
+       font-family:monospace;\r
+       font-size:13px;\r
+       white-space:pre;\r
+       background-image:url("images/line-numbers.png");\r
+       background-repeat:repeat-y;\r
+       background-position:0 3px;\r
+       line-height:16px;\r
+       height:100%;\r
+}\r
+pre {margin:0;}\r
+html>body{background-position:0 2px;}\r
+P {margin:0;padding:0;border:0;outline:0;display:block;white-space:pre;}\r
+b, i, s, u, a, em, tt, ins, big, cite, strong, var, dfn {text-decoration:none;font-weight:normal;font-style:normal;font-size:13px;}\r
+\r
+body.hide-line-numbers {background:white;margin-left:16px;}\r
+body.show-line-numbers {background-image:url("images/line-numbers.png");margin-left:32px;}
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/codepress.html b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/codepress.html
new file mode 100755 (executable)
index 0000000..20270fe
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html>\r
+<head>\r
+       <title>CodePress - Real Time Syntax Highlighting Editor written in JavaScript</title>\r
+       <meta name="description" content="CodePress - source code editor window" />\r
+\r
+       <script type="text/javascript">\r
+       var language = 'generic';\r
+       var engine = 'older';\r
+       var ua = navigator.userAgent;\r
+       var ts = (new Date).getTime(); // timestamp to avoid cache\r
+       var lh = location.href;\r
+       \r
+       if(ua.match('MSIE')) engine = 'msie';\r
+       else if(ua.match('KHTML')) engine = 'khtml'; \r
+       else if(ua.match('Opera')) engine = 'opera'; \r
+       else if(ua.match('Gecko')) engine = 'gecko';\r
+\r
+       if(lh.match('language=')) language = lh.replace(/.*language=(.*?)(&.*)?$/,'$1');\r
+\r
+       document.write('<link type="text/css" href="codepress.css?ts='+ts+'" rel="stylesheet" />');\r
+       document.write('<link type="text/css" href="languages/'+language+'.css?ts='+ts+'" rel="stylesheet" id="cp-lang-style" />');\r
+       document.write('<scr'+'ipt type="text/javascript" src="engines/'+engine+'.js?ts='+ts+'"></scr'+'ipt>');\r
+       document.write('<scr'+'ipt type="text/javascript" src="languages/'+language+'.js?ts='+ts+'"></scr'+'ipt>');\r
+       </script>\r
+\r
+</head>\r
+\r
+<script type="text/javascript">\r
+if(engine == "msie" || engine == "gecko") document.write('<body><pre> </pre></body>');\r
+else if(engine == "opera") document.write('<body></body>');\r
+// else if(engine == "khtml") document.write('<body> </body>');\r
+</script>\r
+\r
+</html>\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/codepress.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/codepress.js
new file mode 100755 (executable)
index 0000000..96ea2e3
--- /dev/null
@@ -0,0 +1,138 @@
+/*\r
+ * CodePress - Real Time Syntax Highlighting Editor written in JavaScript - http://codepress.org/\r
+ * \r
+ * Copyright (C) 2006 Fernando M.A.d.S. <fermads@gmail.com>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify it under the terms of the \r
+ * GNU Lesser General Public License as published by the Free Software Foundation.\r
+ * \r
+ * Read the full licence: http://www.opensource.org/licenses/lgpl-license.php\r
+ */\r
+\r
+CodePress = function(obj) {\r
+       var self = document.createElement('iframe');\r
+       self.textarea = obj;\r
+       self.textarea.disabled = true;\r
+       self.textarea.style.overflow = 'hidden';\r
+       self.style.height = self.textarea.clientHeight +'px';\r
+       self.style.width = self.textarea.clientWidth +'px';\r
+       self.textarea.style.overflow = 'auto';\r
+       self.style.border = '1px solid gray';\r
+       self.frameBorder = 0; // remove IE internal iframe border\r
+       self.style.visibility = 'hidden';\r
+       self.style.position = 'absolute';\r
+       self.options = self.textarea.className;\r
+       \r
+       self.initialize = function() {\r
+               self.editor = self.contentWindow.CodePress;\r
+               self.editor.body = self.contentWindow.document.getElementsByTagName('body')[0];\r
+               self.editor.setCode(self.textarea.value);\r
+               self.setOptions();\r
+               self.editor.syntaxHighlight('init');\r
+               self.textarea.style.display = 'none';\r
+               self.style.position = 'static';\r
+               self.style.visibility = 'visible';\r
+               self.style.display = 'inline';\r
+       }\r
+       \r
+       // obj can by a textarea id or a string (code)\r
+       self.edit = function(obj,language) {\r
+               if(obj) self.textarea.value = document.getElementById(obj) ? document.getElementById(obj).value : obj;\r
+               if(!self.textarea.disabled) return;\r
+               self.language = language ? language : self.getLanguage();\r
+               self.src = CodePress.path+'codepress.html?language='+self.language+'&ts='+(new Date).getTime();\r
+               if(self.attachEvent) self.attachEvent('onload',self.initialize);\r
+               else self.addEventListener('load',self.initialize,false);\r
+       }\r
+\r
+       self.getLanguage = function() {\r
+               for (language in CodePress.languages) \r
+                       if(self.options.match('\\b'+language+'\\b')) \r
+                               return CodePress.languages[language] ? language : 'generic';\r
+       }\r
+       \r
+       self.setOptions = function() {\r
+               if(self.options.match('autocomplete-off')) self.toggleAutoComplete();\r
+               if(self.options.match('readonly-on')) self.toggleReadOnly();\r
+               if(self.options.match('linenumbers-off')) self.toggleLineNumbers();\r
+       }\r
+       \r
+       self.getCode = function() {\r
+               return self.textarea.disabled ? self.editor.getCode() : self.textarea.value;\r
+       }\r
+\r
+       self.setCode = function(code) {\r
+               self.textarea.disabled ? self.editor.setCode(code) : self.textarea.value = code;\r
+       }\r
+\r
+       self.toggleAutoComplete = function() {\r
+               self.editor.autocomplete = (self.editor.autocomplete) ? false : true;\r
+       }\r
+       \r
+       self.toggleReadOnly = function() {\r
+               self.textarea.readOnly = (self.textarea.readOnly) ? false : true;\r
+               if(self.style.display != 'none') // prevent exception on FF + iframe with display:none\r
+                       self.editor.readOnly(self.textarea.readOnly ? true : false);\r
+       }\r
+       \r
+       self.toggleLineNumbers = function() {\r
+               var cn = self.editor.body.className;\r
+               self.editor.body.className = (cn==''||cn=='show-line-numbers') ? 'hide-line-numbers' : 'show-line-numbers';\r
+       }\r
+       \r
+       self.toggleEditor = function() {\r
+               if(self.textarea.disabled) {\r
+                       self.textarea.value = self.getCode();\r
+                       self.textarea.disabled = false;\r
+                       self.style.display = 'none';\r
+                       self.textarea.style.display = 'inline';\r
+               }\r
+               else {\r
+                       self.textarea.disabled = true;\r
+                       self.setCode(self.textarea.value);\r
+                       self.editor.syntaxHighlight('init');\r
+                       self.style.display = 'inline';\r
+                       self.textarea.style.display = 'none';\r
+               }\r
+       }\r
+\r
+       self.edit();\r
+       return self;\r
+}\r
+\r
+CodePress.languages = {        \r
+       csharp : 'C#', \r
+       css : 'CSS', \r
+       generic : 'Generic',\r
+       html : 'HTML',\r
+       java : 'Java', \r
+       javascript : 'JavaScript', \r
+       perl : 'Perl', \r
+       ruby : 'Ruby',  \r
+       php : 'PHP', \r
+       text : 'Text', \r
+       sql : 'SQL',\r
+       vbscript : 'VBScript'\r
+}\r
+\r
+\r
+CodePress.run = function() {\r
+       s = document.getElementsByTagName('script');\r
+       for(var i=0,n=s.length;i<n;i++) {\r
+               if(s[i].src.match('codepress.js')) {\r
+                       CodePress.path = s[i].src.replace('codepress.js','');\r
+               }\r
+       }\r
+       t = document.getElementsByTagName('textarea');\r
+       for(var i=0,n=t.length;i<n;i++) {\r
+               if(t[i].className.match('codepress')) {\r
+                       id = t[i].id;\r
+                       t[i].id = id+'_cp';\r
+                       eval(id+' = new CodePress(t[i])');\r
+                       t[i].parentNode.insertBefore(eval(id), t[i]);\r
+               } \r
+       }\r
+}\r
+\r
+if(window.attachEvent) window.attachEvent('onload',CodePress.run);\r
+else window.addEventListener('DOMContentLoaded',CodePress.run,false);\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/engines/gecko.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/engines/gecko.js
new file mode 100755 (executable)
index 0000000..a9e38a9
--- /dev/null
@@ -0,0 +1,293 @@
+/*\r
+ * CodePress - Real Time Syntax Highlighting Editor written in JavaScript - http://codepress.org/\r
+ * \r
+ * Copyright (C) 2007 Fernando M.A.d.S. <fermads@gmail.com>\r
+ *\r
+ * Developers:\r
+ *             Fernando M.A.d.S. <fermads@gmail.com>\r
+ *             Michael Hurni <michael.hurni@gmail.com>\r
+ * Contributors:       \r
+ *             Martin D. Kirk\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify it under the terms of the \r
+ * GNU Lesser General Public License as published by the Free Software Foundation.\r
+ * \r
+ * Read the full licence: http://www.opensource.org/licenses/lgpl-license.php\r
+ */\r
+\r
+CodePress = {\r
+       scrolling : false,\r
+       autocomplete : true,\r
+\r
+       // set initial vars and start sh\r
+       initialize : function() {\r
+               if(typeof(editor)=='undefined' && !arguments[0]) return;\r
+               body = document.getElementsByTagName('body')[0];\r
+               body.innerHTML = body.innerHTML.replace(/\n/g,"");\r
+               chars = '|32|46|62|8|'; // charcodes that trigger syntax highlighting\r
+               cc = '\u2009'; // carret char\r
+               editor = document.getElementsByTagName('pre')[0];\r
+               document.designMode = 'on';\r
+               document.addEventListener('keypress', this.keyHandler, true);\r
+               window.addEventListener('scroll', function() { if(!CodePress.scrolling) CodePress.syntaxHighlight('scroll') }, false);\r
+               completeChars = this.getCompleteChars();\r
+               completeEndingChars =  this.getCompleteEndingChars();\r
+       },\r
+\r
+       // treat key bindings\r
+       keyHandler : function(evt) {\r
+       keyCode = evt.keyCode;  \r
+               charCode = evt.charCode;\r
+               fromChar = String.fromCharCode(charCode);\r
+\r
+               if((evt.ctrlKey || evt.metaKey) && evt.shiftKey && charCode!=90)  { // shortcuts = ctrl||appleKey+shift+key!=z(undo) \r
+                       CodePress.shortcuts(charCode?charCode:keyCode);\r
+               }\r
+               else if( (completeEndingChars.indexOf('|'+fromChar+'|')!= -1 || completeChars.indexOf('|'+fromChar+'|')!=-1) && CodePress.autocomplete) { // auto complete\r
+                       if(!CodePress.completeEnding(fromChar))\r
+                            CodePress.complete(fromChar);\r
+               }\r
+           else if(chars.indexOf('|'+charCode+'|')!=-1||keyCode==13) { // syntax highlighting\r
+                       top.setTimeout(function(){CodePress.syntaxHighlight('generic');},100);\r
+               }\r
+               else if(keyCode==9 || evt.tabKey) {  // snippets activation (tab)\r
+                       CodePress.snippets(evt);\r
+               }\r
+               else if(keyCode==46||keyCode==8) { // save to history when delete or backspace pressed\r
+                       CodePress.actions.history[CodePress.actions.next()] = editor.innerHTML;\r
+               }\r
+               else if((charCode==122||charCode==121||charCode==90) && evt.ctrlKey) { // undo and redo\r
+                       (charCode==121||evt.shiftKey) ? CodePress.actions.redo() :  CodePress.actions.undo(); \r
+                       evt.preventDefault();\r
+               }\r
+               else if(charCode==118 && evt.ctrlKey)  { // handle paste\r
+                       top.setTimeout(function(){CodePress.syntaxHighlight('generic');},100);\r
+               }\r
+               else if(charCode==99 && evt.ctrlKey)  { // handle cut\r
+                       //alert(window.getSelection().getRangeAt(0).toString().replace(/\t/g,'FFF'));\r
+               }\r
+\r
+       },\r
+\r
+       // put cursor back to its original position after every parsing\r
+       findString : function() {\r
+               if(self.find(cc))\r
+                       window.getSelection().getRangeAt(0).deleteContents();\r
+       },\r
+       \r
+       // split big files, highlighting parts of it\r
+       split : function(code,flag) {\r
+               if(flag=='scroll') {\r
+                       this.scrolling = true;\r
+                       return code;\r
+               }\r
+               else {\r
+                       this.scrolling = false;\r
+                       mid = code.indexOf(cc);\r
+                       if(mid-2000<0) {ini=0;end=4000;}\r
+                       else if(mid+2000>code.length) {ini=code.length-4000;end=code.length;}\r
+                       else {ini=mid-2000;end=mid+2000;}\r
+                       code = code.substring(ini,end);\r
+                       return code;\r
+               }\r
+       },\r
+       \r
+       getEditor : function() {\r
+               if(!document.getElementsByTagName('pre')[0]) {\r
+                       body = document.getElementsByTagName('body')[0];\r
+                       if(!body.innerHTML) return body;\r
+                       if(body.innerHTML=="<br>") body.innerHTML = "<pre> </pre>";\r
+                       else body.innerHTML = "<pre>"+body.innerHTML+"</pre>";\r
+               }\r
+               return document.getElementsByTagName('pre')[0];\r
+       },\r
+       \r
+       // syntax highlighting parser\r
+       syntaxHighlight : function(flag) {\r
+               //if(document.designMode=='off') document.designMode='on'\r
+               if(flag != 'init') { window.getSelection().getRangeAt(0).insertNode(document.createTextNode(cc));}\r
+               editor = CodePress.getEditor();\r
+               o = editor.innerHTML;\r
+               o = o.replace(/<br>/g,'\n');\r
+               o = o.replace(/<.*?>/g,'');\r
+               x = z = this.split(o,flag);\r
+               x = x.replace(/\n/g,'<br>');\r
+\r
+               if(arguments[1]&&arguments[2]) x = x.replace(arguments[1],arguments[2]);\r
+       \r
+               for(i=0;i<Language.syntax.length;i++) \r
+                       x = x.replace(Language.syntax[i].input,Language.syntax[i].output);\r
+\r
+               editor.innerHTML = this.actions.history[this.actions.next()] = (flag=='scroll') ? x : o.split(z).join(x);\r
+               if(flag!='init') this.findString();\r
+       },\r
+       \r
+       getLastWord : function() {\r
+               var rangeAndCaret = CodePress.getRangeAndCaret();\r
+               words = rangeAndCaret[0].substring(rangeAndCaret[1]-40,rangeAndCaret[1]);\r
+               words = words.replace(/[\s\n\r\);\W]/g,'\n').split('\n');\r
+               return words[words.length-1].replace(/[\W]/gi,'').toLowerCase();\r
+       },\r
+       \r
+       snippets : function(evt) {\r
+               var snippets = Language.snippets;       \r
+               var trigger = this.getLastWord();\r
+               for (var i=0; i<snippets.length; i++) {\r
+                       if(snippets[i].input == trigger) {\r
+                               var content = snippets[i].output.replace(/</g,'&lt;');\r
+                               content = content.replace(/>/g,'&gt;');\r
+                               if(content.indexOf('$0')<0) content += cc;\r
+                               else content = content.replace(/\$0/,cc);\r
+                               content = content.replace(/\n/g,'<br>');\r
+                               var pattern = new RegExp(trigger+cc,'gi');\r
+                               evt.preventDefault(); // prevent the tab key from being added\r
+                               this.syntaxHighlight('snippets',pattern,content);\r
+                       }\r
+               }\r
+       },\r
+       \r
+       readOnly : function() {\r
+               document.designMode = (arguments[0]) ? 'off' : 'on';\r
+       },\r
+\r
+       complete : function(trigger) {\r
+               window.getSelection().getRangeAt(0).deleteContents();\r
+               var complete = Language.complete;\r
+               for (var i=0; i<complete.length; i++) {\r
+                       if(complete[i].input == trigger) {\r
+                               var pattern = new RegExp('\\'+trigger+cc);\r
+                               var content = complete[i].output.replace(/\$0/g,cc);\r
+                               parent.setTimeout(function () { CodePress.syntaxHighlight('complete',pattern,content)},0); // wait for char to appear on screen\r
+                       }\r
+               }\r
+       },\r
+\r
+       getCompleteChars : function() {\r
+               var cChars = '';\r
+               for(var i=0;i<Language.complete.length;i++)\r
+                       cChars += '|'+Language.complete[i].input;\r
+               return cChars+'|';\r
+       },\r
+       \r
+       getCompleteEndingChars : function() {\r
+               var cChars = '';\r
+               for(var i=0;i<Language.complete.length;i++)\r
+                       cChars += '|'+Language.complete[i].output.charAt(Language.complete[i].output.length-1);\r
+               return cChars+'|';\r
+       },\r
+       \r
+       completeEnding : function(trigger) {\r
+               var range = window.getSelection().getRangeAt(0);\r
+               try {\r
+                       range.setEnd(range.endContainer, range.endOffset+1)\r
+               }\r
+               catch(e) {\r
+                       return false;\r
+               }\r
+               var next_character = range.toString()\r
+               range.setEnd(range.endContainer, range.endOffset-1)\r
+               if(next_character != trigger) return false;\r
+               else {\r
+                       range.setEnd(range.endContainer, range.endOffset+1)\r
+                       range.deleteContents();\r
+                       return true;\r
+               }\r
+       },\r
+       \r
+       shortcuts : function() {\r
+               var cCode = arguments[0];\r
+               if(cCode==13) cCode = '[enter]';\r
+               else if(cCode==32) cCode = '[space]';\r
+               else cCode = '['+String.fromCharCode(charCode).toLowerCase()+']';\r
+               for(var i=0;i<Language.shortcuts.length;i++)\r
+                       if(Language.shortcuts[i].input == cCode)\r
+                               this.insertCode(Language.shortcuts[i].output,false);\r
+       },\r
+       \r
+       getRangeAndCaret : function() { \r
+               var range = window.getSelection().getRangeAt(0);\r
+               var range2 = range.cloneRange();\r
+               var node = range.endContainer;                  \r
+               var caret = range.endOffset;\r
+               range2.selectNode(node);        \r
+               return [range2.toString(),caret];\r
+       },\r
+       \r
+       insertCode : function(code,replaceCursorBefore) {\r
+               var range = window.getSelection().getRangeAt(0);\r
+               var node = window.document.createTextNode(code);\r
+               var selct = window.getSelection();\r
+               var range2 = range.cloneRange();\r
+               // Insert text at cursor position\r
+               selct.removeAllRanges();\r
+               range.deleteContents();\r
+               range.insertNode(node);\r
+               // Move the cursor to the end of text\r
+               range2.selectNode(node);                \r
+               range2.collapse(replaceCursorBefore);\r
+               selct.removeAllRanges();\r
+               selct.addRange(range2);\r
+       },\r
+       \r
+       // get code from editor\r
+       getCode : function() {\r
+               if(!document.getElementsByTagName('pre')[0] || editor.innerHTML == '')\r
+                       editor = CodePress.getEditor();\r
+               var code = editor.innerHTML;\r
+               code = code.replace(/<br>/g,'\n');\r
+               code = code.replace(/\u2009/g,'');\r
+               code = code.replace(/<.*?>/g,'');\r
+               code = code.replace(/&lt;/g,'<');\r
+               code = code.replace(/&gt;/g,'>');\r
+               code = code.replace(/&amp;/gi,'&');\r
+               return code;\r
+       },\r
+\r
+       // put code inside editor\r
+       setCode : function() {\r
+               var code = arguments[0];\r
+               code = code.replace(/\u2009/gi,'');\r
+               code = code.replace(/&/gi,'&amp;');\r
+               code = code.replace(/</g,'&lt;');\r
+               code = code.replace(/>/g,'&gt;');\r
+               editor.innerHTML = code;\r
+               if (code == '')\r
+                       document.getElementsByTagName('body')[0].innerHTML = '';\r
+       },\r
+\r
+       // undo and redo methods\r
+       actions : {\r
+               pos : -1, // actual history position\r
+               history : [], // history vector\r
+               \r
+               undo : function() {\r
+                       editor = CodePress.getEditor();\r
+                       if(editor.innerHTML.indexOf(cc)==-1){\r
+                               if(editor.innerHTML != " ")\r
+                                       window.getSelection().getRangeAt(0).insertNode(document.createTextNode(cc));\r
+                               this.history[this.pos] = editor.innerHTML;\r
+                       }\r
+                       this.pos --;\r
+                       if(typeof(this.history[this.pos])=='undefined') this.pos ++;\r
+                       editor.innerHTML = this.history[this.pos];\r
+                       if(editor.innerHTML.indexOf(cc)>-1) editor.innerHTML+=cc;\r
+                       CodePress.findString();\r
+               },\r
+               \r
+               redo : function() {\r
+                       // editor = CodePress.getEditor();\r
+                       this.pos++;\r
+                       if(typeof(this.history[this.pos])=='undefined') this.pos--;\r
+                       editor.innerHTML = this.history[this.pos];\r
+                       CodePress.findString();\r
+               },\r
+               \r
+               next : function() { // get next vector position and clean old ones\r
+                       if(this.pos>20) this.history[this.pos-21] = undefined;\r
+                       return ++this.pos;\r
+               }\r
+       }\r
+}\r
+\r
+Language={};\r
+window.addEventListener('load', function() { CodePress.initialize('new'); }, true);
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/engines/khtml.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/engines/khtml.js
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/engines/msie.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/engines/msie.js
new file mode 100755 (executable)
index 0000000..fd609b2
--- /dev/null
@@ -0,0 +1,304 @@
+/*\r
+ * CodePress - Real Time Syntax Highlighting Editor written in JavaScript - http://codepress.org/\r
+ * \r
+ * Copyright (C) 2007 Fernando M.A.d.S. <fermads@gmail.com>\r
+ *\r
+ * Developers:\r
+ *             Fernando M.A.d.S. <fermads@gmail.com>\r
+ *             Michael Hurni <michael.hurni@gmail.com>\r
+ * Contributors:       \r
+ *             Martin D. Kirk\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify it under the terms of the \r
+ * GNU Lesser General Public License as published by the Free Software Foundation.\r
+ * \r
+ * Read the full licence: http://www.opensource.org/licenses/lgpl-license.php\r
+ */\r
+\r
+CodePress = {\r
+       scrolling : false,\r
+       autocomplete : true,\r
+       \r
+       // set initial vars and start sh\r
+       initialize : function() {\r
+               if(typeof(editor)=='undefined' && !arguments[0]) return;\r
+               chars = '|32|46|62|'; // charcodes that trigger syntax highlighting\r
+               cc = '\u2009'; // carret char\r
+               editor = document.getElementsByTagName('pre')[0];\r
+               editor.contentEditable = 'true';\r
+               document.getElementsByTagName('body')[0].onfocus = function() {editor.focus();}\r
+               document.attachEvent('onkeydown', this.metaHandler);\r
+               document.attachEvent('onkeypress', this.keyHandler);\r
+               window.attachEvent('onscroll', function() { if(!CodePress.scrolling) setTimeout(function(){CodePress.syntaxHighlight('scroll')},1)});\r
+               completeChars = this.getCompleteChars();\r
+               completeEndingChars =  this.getCompleteEndingChars();\r
+               setTimeout(function() { window.scroll(0,0) },50); // scroll IE to top\r
+       },\r
+       \r
+       // treat key bindings\r
+       keyHandler : function(evt) {\r
+               charCode = evt.keyCode;\r
+               fromChar = String.fromCharCode(charCode);\r
+               \r
+               if( (completeEndingChars.indexOf('|'+fromChar+'|')!= -1 || completeChars.indexOf('|'+fromChar+'|')!=-1  )&& CodePress.autocomplete) { // auto complete\r
+                       if(!CodePress.completeEnding(fromChar))\r
+                            CodePress.complete(fromChar);\r
+               }\r
+           else if(chars.indexOf('|'+charCode+'|')!=-1||charCode==13) { // syntax highlighting\r
+                       CodePress.syntaxHighlight('generic');\r
+               }\r
+       },\r
+\r
+       metaHandler : function(evt) {\r
+               keyCode = evt.keyCode;\r
+               \r
+               if(keyCode==9 || evt.tabKey) { \r
+                       CodePress.snippets();\r
+               }\r
+               else if((keyCode==122||keyCode==121||keyCode==90) && evt.ctrlKey) { // undo and redo\r
+                       (keyCode==121||evt.shiftKey) ? CodePress.actions.redo() :  CodePress.actions.undo(); \r
+                       evt.returnValue = false;\r
+               }\r
+               else if(keyCode==34||keyCode==33) { // handle page up/down for IE\r
+                       self.scrollBy(0, (keyCode==34) ? 200 : -200); \r
+                       evt.returnValue = false;\r
+               }\r
+               else if(keyCode==46||keyCode==8) { // save to history when delete or backspace pressed\r
+                       CodePress.actions.history[CodePress.actions.next()] = editor.innerHTML;\r
+               }\r
+               else if((evt.ctrlKey || evt.metaKey) && evt.shiftKey && keyCode!=90)  { // shortcuts = ctrl||appleKey+shift+key!=z(undo) \r
+                       CodePress.shortcuts(keyCode);\r
+                       evt.returnValue = false;\r
+               }\r
+               else if(keyCode==86 && evt.ctrlKey)  { // handle paste\r
+                       window.clipboardData.setData('Text',window.clipboardData.getData('Text').replace(/\t/g,'\u2008'));\r
+                       top.setTimeout(function(){CodePress.syntaxHighlight('paste');},10);\r
+               }\r
+               else if(keyCode==67 && evt.ctrlKey)  { // handle cut\r
+                       // window.clipboardData.setData('Text',x[0]);\r
+                       // code = window.clipboardData.getData('Text');\r
+               }\r
+       },\r
+\r
+       // put cursor back to its original position after every parsing\r
+       \r
+       \r
+       findString : function() {\r
+               range = self.document.body.createTextRange();\r
+               if(range.findText(cc)){\r
+                       range.select();\r
+                       range.text = '';\r
+               }\r
+       },\r
+       \r
+       // split big files, highlighting parts of it\r
+       split : function(code,flag) {\r
+               if(flag=='scroll') {\r
+                       this.scrolling = true;\r
+                       return code;\r
+               }\r
+               else {\r
+                       this.scrolling = false;\r
+                       mid = code.indexOf(cc);\r
+                       if(mid-2000<0) {ini=0;end=4000;}\r
+                       else if(mid+2000>code.length) {ini=code.length-4000;end=code.length;}\r
+                       else {ini=mid-2000;end=mid+2000;}\r
+                       code = code.substring(ini,end);\r
+                       return code.substring(code.indexOf('<P>'),code.lastIndexOf('</P>')+4);\r
+               }\r
+       },\r
+       \r
+       // syntax highlighting parser\r
+       syntaxHighlight : function(flag) {\r
+               if(flag!='init') document.selection.createRange().text = cc;\r
+               o = editor.innerHTML;\r
+               if(flag=='paste') { // fix pasted text\r
+                       o = o.replace(/<BR>/g,'\r\n'); \r
+                       o = o.replace(/\u2008/g,'\t');\r
+               }\r
+               o = o.replace(/<P>/g,'\n');\r
+               o = o.replace(/<\/P>/g,'\r');\r
+               o = o.replace(/<.*?>/g,'');\r
+               o = o.replace(/&nbsp;/g,'');                    \r
+               o = '<PRE><P>'+o+'</P></PRE>';\r
+               o = o.replace(/\n\r/g,'<P></P>');\r
+               o = o.replace(/\n/g,'<P>');\r
+               o = o.replace(/\r/g,'<\/P>');\r
+               o = o.replace(/<P>(<P>)+/,'<P>');\r
+               o = o.replace(/<\/P>(<\/P>)+/,'</P>');\r
+               o = o.replace(/<P><\/P>/g,'<P><BR/></P>');\r
+               x = z = this.split(o,flag);\r
+\r
+               if(arguments[1]&&arguments[2]) x = x.replace(arguments[1],arguments[2]);\r
+       \r
+               for(i=0;i<Language.syntax.length;i++) \r
+                       x = x.replace(Language.syntax[i].input,Language.syntax[i].output);\r
+                       \r
+               editor.innerHTML = this.actions.history[this.actions.next()] = (flag=='scroll') ? x : o.replace(z,x);\r
+               if(flag!='init') this.findString();\r
+       },\r
+\r
+       snippets : function(evt) {\r
+               var snippets = Language.snippets;\r
+               var trigger = this.getLastWord();\r
+               for (var i=0; i<snippets.length; i++) {\r
+                       if(snippets[i].input == trigger) {\r
+                               var content = snippets[i].output.replace(/</g,'&lt;');\r
+                               content = content.replace(/>/g,'&gt;');\r
+                               if(content.indexOf('$0')<0) content += cc;\r
+                               else content = content.replace(/\$0/,cc);\r
+                               content = content.replace(/\n/g,'</P><P>');\r
+                               var pattern = new RegExp(trigger+cc,"gi");\r
+                               this.syntaxHighlight('snippets',pattern,content);\r
+                       }\r
+               }\r
+       },\r
+       \r
+       readOnly : function() {\r
+               editor.contentEditable = (arguments[0]) ? 'false' : 'true';\r
+       },\r
+       \r
+       complete : function(trigger) {\r
+               var complete = Language.complete;\r
+               for (var i=0; i<complete.length; i++) {\r
+                       if(complete[i].input == trigger) {\r
+                               var pattern = new RegExp('\\'+trigger+cc);\r
+                               var content = complete[i].output.replace(/\$0/g,cc);\r
+                               setTimeout(function () { CodePress.syntaxHighlight('complete',pattern,content)},0); // wait for char to appear on screen\r
+                       }\r
+               }\r
+       },\r
+       \r
+       getCompleteChars : function() {\r
+               var cChars = '';\r
+               for(var i=0;i<Language.complete.length;i++)\r
+                       cChars += '|'+Language.complete[i].input;\r
+               return cChars+'|';\r
+       },\r
+\r
+       getCompleteEndingChars : function() {\r
+               var cChars = '';\r
+               for(var i=0;i<Language.complete.length;i++)\r
+                       cChars += '|'+Language.complete[i].output.charAt(Language.complete[i].output.length-1);\r
+               return cChars+'|';\r
+       },\r
+\r
+       completeEnding : function(trigger) {\r
+               var range = document.selection.createRange();\r
+               try {\r
+                       range.moveEnd('character', 1)\r
+               }\r
+               catch(e) {\r
+                       return false;\r
+               }\r
+               var next_character = range.text\r
+               range.moveEnd('character', -1)\r
+               if(next_character != trigger )  return false;\r
+               else {\r
+                       range.moveEnd('character', 1)\r
+                       range.text=''\r
+                       return true;\r
+               }\r
+       },      \r
+\r
+       shortcuts : function() {\r
+               var cCode = arguments[0];\r
+               if(cCode==13) cCode = '[enter]';\r
+               else if(cCode==32) cCode = '[space]';\r
+               else cCode = '['+String.fromCharCode(keyCode).toLowerCase()+']';\r
+               for(var i=0;i<Language.shortcuts.length;i++)\r
+                       if(Language.shortcuts[i].input == cCode)\r
+                               this.insertCode(Language.shortcuts[i].output,false);\r
+       },\r
+       \r
+       getLastWord : function() {\r
+               var rangeAndCaret = CodePress.getRangeAndCaret();\r
+               words = rangeAndCaret[0].substring(rangeAndCaret[1]-40,rangeAndCaret[1]);\r
+               words = words.replace(/[\s\n\r\);\W]/g,'\n').split('\n');\r
+               return words[words.length-1].replace(/[\W]/gi,'').toLowerCase();\r
+       }, \r
+\r
+       getRangeAndCaret : function() { \r
+               var range = document.selection.createRange();\r
+               var caret = Math.abs(range.moveStart('character', -1000000)+1);\r
+               range = this.getCode();\r
+               range = range.replace(/\n\r/gi,'  ');\r
+               range = range.replace(/\n/gi,'');\r
+               return [range.toString(),caret];\r
+       },\r
+       \r
+       insertCode : function(code,replaceCursorBefore) {\r
+               var repdeb = '';\r
+               var repfin = '';\r
+               \r
+               if(replaceCursorBefore) { repfin = code; }\r
+               else { repdeb = code; }\r
+               \r
+               if(typeof document.selection != 'undefined') {\r
+                       var range = document.selection.createRange();\r
+                       range.text = repdeb + repfin;\r
+                       range = document.selection.createRange();\r
+                       range.move('character', -repfin.length);\r
+                       range.select(); \r
+               }       \r
+       },\r
+\r
+       // get code from editor \r
+       getCode : function() {\r
+               var code = editor.innerHTML;\r
+               code = code.replace(/<br>/g,'\n');\r
+               code = code.replace(/<\/p>/gi,'\r');\r
+               code = code.replace(/<p>/i,''); // IE first line fix\r
+               code = code.replace(/<p>/gi,'\n');\r
+               code = code.replace(/&nbsp;/gi,'');\r
+               code = code.replace(/\u2009/g,'');\r
+               code = code.replace(/<.*?>/g,'');\r
+               code = code.replace(/&lt;/g,'<');\r
+               code = code.replace(/&gt;/g,'>');\r
+               code = code.replace(/&amp;/gi,'&');\r
+               return code;\r
+       },\r
+\r
+       // put code inside editor\r
+       setCode : function() {\r
+               var code = arguments[0];\r
+               code = code.replace(/\u2009/gi,'');\r
+               code = code.replace(/&/gi,'&amp;');             \r
+               code = code.replace(/</g,'&lt;');\r
+        code = code.replace(/>/g,'&gt;');\r
+               editor.innerHTML = '<pre>'+code+'</pre>';\r
+       },\r
+\r
+       \r
+       // undo and redo methods\r
+       actions : {\r
+               pos : -1, // actual history position\r
+               history : [], // history vector\r
+               \r
+               undo : function() {\r
+                       if(editor.innerHTML.indexOf(cc)==-1){\r
+                               document.selection.createRange().text = cc;\r
+                               this.history[this.pos] = editor.innerHTML;\r
+                       }\r
+                       this.pos--;\r
+                       if(typeof(this.history[this.pos])=='undefined') this.pos++;\r
+                       editor.innerHTML = this.history[this.pos];\r
+                       CodePress.findString();\r
+               },\r
+               \r
+               redo : function() {\r
+                       this.pos++;\r
+                       if(typeof(this.history[this.pos])=='undefined') this.pos--;\r
+                       editor.innerHTML = this.history[this.pos];\r
+                       CodePress.findString();\r
+               },\r
+               \r
+               next : function() { // get next vector position and clean old ones\r
+                       if(this.pos>20) this.history[this.pos-21] = undefined;\r
+                       return ++this.pos;\r
+               }\r
+       }\r
+}\r
+\r
+Language={};\r
+window.attachEvent('onload', function() { CodePress.initialize('new');});
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/engines/older.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/engines/older.js
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/engines/opera.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/engines/opera.js
new file mode 100755 (executable)
index 0000000..152c763
--- /dev/null
@@ -0,0 +1,260 @@
+/*\r
+ * CodePress - Real Time Syntax Highlighting Editor written in JavaScript - http://codepress.org/\r
+ * \r
+ * Copyright (C) 2007 Fernando M.A.d.S. <fermads@gmail.com>\r
+ *\r
+ * Contributors :\r
+ *\r
+ *     Michael Hurni <michael.hurni@gmail.com>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify it under the terms of the \r
+ * GNU Lesser General Public License as published by the Free Software Foundation.\r
+ * \r
+ * Read the full licence: http://www.opensource.org/licenses/lgpl-license.php\r
+ */\r
+\r
+\r
+CodePress = {\r
+       scrolling : false,\r
+       autocomplete : true,\r
+\r
+       // set initial vars and start sh\r
+       initialize : function() {\r
+               if(typeof(editor)=='undefined' && !arguments[0]) return;\r
+               chars = '|32|46|62|'; // charcodes that trigger syntax highlighting\r
+               cc = '\u2009'; // control char\r
+               editor = document.getElementsByTagName('body')[0];\r
+               document.designMode = 'on';\r
+               document.addEventListener('keyup', this.keyHandler, true);\r
+               window.addEventListener('scroll', function() { if(!CodePress.scrolling) CodePress.syntaxHighlight('scroll') }, false);\r
+               completeChars = this.getCompleteChars();\r
+//             CodePress.syntaxHighlight('init');\r
+       },\r
+\r
+       // treat key bindings\r
+       keyHandler : function(evt) {\r
+       keyCode = evt.keyCode;  \r
+               charCode = evt.charCode;\r
+\r
+               if((evt.ctrlKey || evt.metaKey) && evt.shiftKey && charCode!=90)  { // shortcuts = ctrl||appleKey+shift+key!=z(undo) \r
+                       CodePress.shortcuts(charCode?charCode:keyCode);\r
+               }\r
+               else if(completeChars.indexOf('|'+String.fromCharCode(charCode)+'|')!=-1 && CodePress.autocomplete) { // auto complete\r
+                       CodePress.complete(String.fromCharCode(charCode));\r
+               }\r
+           else if(chars.indexOf('|'+charCode+'|')!=-1||keyCode==13) { // syntax highlighting\r
+                       CodePress.syntaxHighlight('generic');\r
+               }\r
+               else if(keyCode==9 || evt.tabKey) {  // snippets activation (tab)\r
+                       CodePress.snippets(evt);\r
+               }\r
+               else if(keyCode==46||keyCode==8) { // save to history when delete or backspace pressed\r
+                       CodePress.actions.history[CodePress.actions.next()] = editor.innerHTML;\r
+               }\r
+               else if((charCode==122||charCode==121||charCode==90) && evt.ctrlKey) { // undo and redo\r
+                       (charCode==121||evt.shiftKey) ? CodePress.actions.redo() :  CodePress.actions.undo(); \r
+                       evt.preventDefault();\r
+               }\r
+               else if(keyCode==86 && evt.ctrlKey)  { // paste\r
+                       // TODO: pasted text should be parsed and highlighted\r
+               }\r
+       },\r
+\r
+       // put cursor back to its original position after every parsing\r
+       findString : function() {\r
+               var sel = window.getSelection();\r
+               var range = window.document.createRange();\r
+               var span = window.document.getElementsByTagName('span')[0];\r
+                       \r
+               range.selectNode(span);\r
+               sel.removeAllRanges();\r
+               sel.addRange(range);\r
+               span.parentNode.removeChild(span);\r
+               //if(self.find(cc))\r
+               //window.getSelection().getRangeAt(0).deleteContents();\r
+       },\r
+       \r
+       // split big files, highlighting parts of it\r
+       split : function(code,flag) {\r
+               if(flag=='scroll') {\r
+                       this.scrolling = true;\r
+                       return code;\r
+               }\r
+               else {\r
+                       this.scrolling = false;\r
+                       mid = code.indexOf('<SPAN>');\r
+                       if(mid-2000<0) {ini=0;end=4000;}\r
+                       else if(mid+2000>code.length) {ini=code.length-4000;end=code.length;}\r
+                       else {ini=mid-2000;end=mid+2000;}\r
+                       code = code.substring(ini,end);\r
+                       return code;\r
+               }\r
+       },\r
+       \r
+       // syntax highlighting parser\r
+       syntaxHighlight : function(flag) {\r
+               //if(document.designMode=='off') document.designMode='on'\r
+               if(flag!='init') {\r
+                       var span = document.createElement('span');\r
+                       window.getSelection().getRangeAt(0).insertNode(span);\r
+               }\r
+\r
+               o = editor.innerHTML;\r
+//             o = o.replace(/<br>/g,'\r\n');\r
+//             o = o.replace(/<(b|i|s|u|a|em|tt|ins|big|cite|strong)?>/g,'');\r
+               //alert(o)\r
+               o = o.replace(/<(?!span|\/span|br).*?>/gi,'');\r
+//             alert(o)\r
+//             x = o;\r
+               x = z = this.split(o,flag);\r
+               //alert(z)\r
+//             x = x.replace(/\r\n/g,'<br>');\r
+               x = x.replace(/\t/g, '        ');\r
+\r
+\r
+               if(arguments[1]&&arguments[2]) x = x.replace(arguments[1],arguments[2]);\r
+       \r
+               for(i=0;i<Language.syntax.length;i++) \r
+                       x = x.replace(Language.syntax[i].input,Language.syntax[i].output);\r
+\r
+               editor.innerHTML = this.actions.history[this.actions.next()] = (flag=='scroll') ? x : o.split(z).join(x); \r
+\r
+               if(flag!='init') this.findString();\r
+       },\r
+       \r
+       getLastWord : function() {\r
+               var rangeAndCaret = CodePress.getRangeAndCaret();\r
+               words = rangeAndCaret[0].substring(rangeAndCaret[1]-40,rangeAndCaret[1]);\r
+               words = words.replace(/[\s\n\r\);\W]/g,'\n').split('\n');\r
+               return words[words.length-1].replace(/[\W]/gi,'').toLowerCase();\r
+       }, \r
+       \r
+       snippets : function(evt) {\r
+               var snippets = Language.snippets;       \r
+               var trigger = this.getLastWord();\r
+               for (var i=0; i<snippets.length; i++) {\r
+                       if(snippets[i].input == trigger) {\r
+                               var content = snippets[i].output.replace(/</g,'&lt;');\r
+                               content = content.replace(/>/g,'&gt;');\r
+                               if(content.indexOf('$0')<0) content += cc;\r
+                               else content = content.replace(/\$0/,cc);\r
+                               content = content.replace(/\n/g,'<br>');\r
+                               var pattern = new RegExp(trigger+cc,'gi');\r
+                               evt.preventDefault(); // prevent the tab key from being added\r
+                               this.syntaxHighlight('snippets',pattern,content);\r
+                       }\r
+               }\r
+       },\r
+       \r
+       readOnly : function() {\r
+               document.designMode = (arguments[0]) ? 'off' : 'on';\r
+       },\r
+\r
+       complete : function(trigger) {\r
+               window.getSelection().getRangeAt(0).deleteContents();\r
+               var complete = Language.complete;\r
+               for (var i=0; i<complete.length; i++) {\r
+                       if(complete[i].input == trigger) {\r
+                               var pattern = new RegExp('\\'+trigger+cc);\r
+                               var content = complete[i].output.replace(/\$0/g,cc);\r
+                               parent.setTimeout(function () { CodePress.syntaxHighlight('complete',pattern,content)},0); // wait for char to appear on screen\r
+                       }\r
+               }\r
+       },\r
+\r
+       getCompleteChars : function() {\r
+               var cChars = '';\r
+               for(var i=0;i<Language.complete.length;i++)\r
+                       cChars += '|'+Language.complete[i].input;\r
+               return cChars+'|';\r
+       },\r
+\r
+       shortcuts : function() {\r
+               var cCode = arguments[0];\r
+               if(cCode==13) cCode = '[enter]';\r
+               else if(cCode==32) cCode = '[space]';\r
+               else cCode = '['+String.fromCharCode(charCode).toLowerCase()+']';\r
+               for(var i=0;i<Language.shortcuts.length;i++)\r
+                       if(Language.shortcuts[i].input == cCode)\r
+                               this.insertCode(Language.shortcuts[i].output,false);\r
+       },\r
+       \r
+       getRangeAndCaret : function() { \r
+               var range = window.getSelection().getRangeAt(0);\r
+               var range2 = range.cloneRange();\r
+               var node = range.endContainer;                  \r
+               var caret = range.endOffset;\r
+               range2.selectNode(node);        \r
+               return [range2.toString(),caret];\r
+       },\r
+       \r
+       insertCode : function(code,replaceCursorBefore) {\r
+               var range = window.getSelection().getRangeAt(0);\r
+               var node = window.document.createTextNode(code);\r
+               var selct = window.getSelection();\r
+               var range2 = range.cloneRange();\r
+               // Insert text at cursor position\r
+               selct.removeAllRanges();\r
+               range.deleteContents();\r
+               range.insertNode(node);\r
+               // Move the cursor to the end of text\r
+               range2.selectNode(node);                \r
+               range2.collapse(replaceCursorBefore);\r
+               selct.removeAllRanges();\r
+               selct.addRange(range2);\r
+       },\r
+       \r
+       // get code from editor\r
+       getCode : function() {\r
+               var code = editor.innerHTML;\r
+               code = code.replace(/<br>/g,'\n');\r
+               code = code.replace(/\u2009/g,'');\r
+               code = code.replace(/<.*?>/g,'');\r
+               code = code.replace(/&lt;/g,'<');\r
+               code = code.replace(/&gt;/g,'>');\r
+               code = code.replace(/&amp;/gi,'&');\r
+               return code;\r
+       },\r
+\r
+       // put code inside editor\r
+       setCode : function() {\r
+               var code = arguments[0];\r
+               code = code.replace(/\u2009/gi,'');\r
+               code = code.replace(/&/gi,'&amp;');\r
+               code = code.replace(/</g,'&lt;');\r
+        code = code.replace(/>/g,'&gt;');\r
+               editor.innerHTML = code;\r
+       },\r
+\r
+       // undo and redo methods\r
+       actions : {\r
+               pos : -1, // actual history position\r
+               history : [], // history vector\r
+               \r
+               undo : function() {\r
+                       if(editor.innerHTML.indexOf(cc)==-1){\r
+                               window.getSelection().getRangeAt(0).insertNode(document.createTextNode(cc));\r
+                               this.history[this.pos] = editor.innerHTML;\r
+                       }\r
+                       this.pos--;\r
+                       if(typeof(this.history[this.pos])=='undefined') this.pos++;\r
+                       editor.innerHTML = this.history[this.pos];\r
+                       CodePress.findString();\r
+               },\r
+               \r
+               redo : function() {\r
+                       this.pos++;\r
+                       if(typeof(this.history[this.pos])=='undefined') this.pos--;\r
+                       editor.innerHTML = this.history[this.pos];\r
+                       CodePress.findString();\r
+               },\r
+               \r
+               next : function() { // get next vector position and clean old ones\r
+                       if(this.pos>20) this.history[this.pos-21] = undefined;\r
+                       return ++this.pos;\r
+               }\r
+       }\r
+}\r
+\r
+Language={};\r
+window.addEventListener('load', function() { CodePress.initialize('new'); }, true);\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/images/line-numbers.png b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/images/line-numbers.png
new file mode 100755 (executable)
index 0000000..ffea4e6
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/images/line-numbers.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/index.html b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/index.html
new file mode 100755 (executable)
index 0000000..703cec2
--- /dev/null
@@ -0,0 +1,443 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+\r
+<html>\r
+<head>\r
+       <title>CodePress - Real Time Syntax Highlighting Editor written in JavaScript</title>\r
+\r
+       <style>\r
+       body {color:#000;background-color:white;font:15px georgia, "Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif; letter-spacing:0.01em;margin:15px;}\r
+       p {margin:0 0 15px 0;}\r
+       a,a:visited {color:#7f0055;}\r
+       select {background:#ffffe1;}\r
+       button {margin-top:5px;}\r
+       button.actions {width:171px;font-family:arial;}\r
+       h1 {color:#7f0055;margin:0;padding:0;font-size:42px;font-weight:normal;}\r
+       h1 a {text-decoration:none;}\r
+       h2 {margin:0;}\r
+       h2 a {text-decoration:none;font-weight:normal;font-size:22px;color:black !important;}\r
+       h3 {font-size:20px;font-weight:normal;padding:0;margin:25px 0 5px 0;color:#7f0055;font-weight:bold;border-bottom:2px dotted #d8d8d8;}\r
+       h4 {font-size:18px;font-weight:normal;z-index:0;}       \r
+       code {color:#0080c0;font-size:13px;font-weight:bold;}\r
+       ol, ul {padding:5px 0 5px 25px;margin:0;}\r
+       ol li, ul li {margin:8px 0 8px 0;}\r
+       \r
+       #logo {text-align:center;background-color:#d6d6d6;padding:10px;-moz-border-radius:5px;border:1px solid silver;}\r
+       #container {width:700px;margin:20px auto;padding:25px;border:3px solid #d9d9d9;-moz-border-radius:10px;background:#f8f8f8;}\r
+       #languages {margin:5px 0;}\r
+       \r
+       #menu {width:100%;background:#7f0055;-moz-border-radius:4px;}\r
+       #menu a {font:bold 17px georgia;color:white;padding:4px;display:block;border-left:1px solid white;text-align:center;text-decoration:none;}\r
+       #menu a:hover {background:#b9669e;} \r
+\r
+       .hidden-code {display:none;}\r
+       .copycode {border:1px dotted gray;padding:10px;background:white;font-family:monospace;color:gray}\r
+       </style>\r
+\r
+</head>\r
+\r
+<body>\r
+<div id="container">\r
+\r
+<div id="logo">\r
+       <h1><a href="http://codepress.org/">CodePress</a></h1>\r
+       <h2><a href="http://codepress.org/">Online Real Time Syntax Highlighting Editor</a></h2>\r
+</div>\r
+\r
+<br />\r
+\r
+<table cellpadding="0" cellspacing="0" id="menu">\r
+<tr>\r
+       <td>\r
+               <a href="http://www.codepress.org/index.php">Home/Download</a>\r
+       </td>\r
+       <td>\r
+               <a href="http://www.codepress.org/install.php">&nbsp;&nbsp;Install&nbsp;&nbsp;</a>\r
+       </td>\r
+       <td>\r
+               <a href="http://www.codepress.org/to-do.php">&nbsp;&nbsp;To-do&nbsp;&nbsp;</a>\r
+       </td>\r
+       <td>\r
+               <a href="http://www.codepress.org/about.php" id="about">&nbsp;&nbsp;About&nbsp;&nbsp;</a>\r
+       </td>\r
+</tr>\r
+</table>\r
+\r
+<h4>\r
+       CodePress is web-based source code editor with syntax highlighting written in JavaScript that colors text in real time while it's being typed in the browser.\r
+</h4>\r
+       \r
+<p>\r
+       Go to <strong><a href="http://codepress.org/">http://codepress.org/</a></strong> for updates.\r
+</p>\r
+\r
+<h3>Demo</h3>\r
+<div id="languages">\r
+       <em>choose example in:</em> \r
+       <button onclick="cp1.edit('cp-php','php')">PHP</button> \r
+       <button onclick="cp1.edit('cp-javascript','javascript')">JavaScript</button> \r
+       <button onclick="cp1.edit('cp-java','java')">Java</button>\r
+       <button onclick="cp1.edit('cp-perl','perl')">Perl</button>\r
+       <button onclick="cp1.edit('cp-sql','sql')">SQL</button> \r
+       <button onclick="cp1.edit('cp-html','html')">HTML</button> \r
+       <button onclick="cp1.edit('cp-css','css')">CSS</button>         \r
+</div>\r
+\r
+<textarea id="cp1" class="codepress php" style="width:700px;height:300px;" wrap="off">\r
+<?php\r
+// Very simple implementation of server side script\r
+\r
+if(isset($_GET['file'])) {\r
+       $file = basename($_GET['file']);\r
+       $full_file = $path['server'].'/'.$path['webdocs'].'/'.$path['files']."/".$file;\r
+       if(file_exists($full_file)) {\r
+               $code = file_get_contents($full_file);\r
+               $code = preg_replace("/>/","&amp;gt;",$code);\r
+               $code = preg_replace("/</","&amp;lt;",$code);\r
+               $language = getLanguage($file);\r
+       }\r
+}\r
+?>\r
+\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html>\r
+<head>\r
+       <title>CodePress - Real Time Syntax Highlighting Editor written in JavaScript</title>\r
+       <link type="text/css" href="languages/codepress-<?=$language?>.css" rel="stylesheet" id="cp-lang-style" />\r
+       <script type="text/javascript" src="codepress.js"></script>\r
+       <script type="text/javascript">\r
+               CodePress.language = '<?=$language?>';\r
+       </script>\r
+</head>\r
+<body id="ffedt"><pre id="ieedt"><?=$code?></pre></body>\r
+</html>\r
+</textarea>\r
+\r
+<br /><br />\r
+\r
+<textarea id="codepress2" class="codepress javascript linenumbers-off" style="width:700px;height:200px;" wrap="off">\r
+//set language\r
+this.setLanguage = function() {\r
+       if(arguments[0]) {\r
+               language = (typeof(Content.languages[arguments[0]])!='undefined') ? arguments[0] : this.setLanguage();\r
+               cpLanguage.innerHTML = Content.languages[language].name;\r
+               if(cpBody.document.designMode=='on') cpBody.document.designMode = 'off';\r
+               CodePress.loadScript(cpBody.document, '../languages/'+language+'.js', function () { cpBody.CodePress.syntaxHighlight('init'); })\r
+               cpBody.document.getElementById('cp-lang-style').href = '../languages/'+language+'.css';\r
+               this.hideMenu();\r
+       }\r
+       else {\r
+               var extension = filename.replace(/.*\.([^\.]+)$/,'$1');\r
+               var aux = false;\r
+               for(lang in Content.languages) {\r
+                       extensions = ','+Content.languages[lang].extensions+',';\r
+                       if(extensions.match(','+extension+',')) aux = lang;\r
+               }\r
+               language = (aux) ? aux : 'generic';\r
+       }\r
+}\r
+</textarea>\r
+\r
+<p>\r
+       <button class="actions" onclick="alert(codepress2.getCode())">get code from editor</button>\r
+       <button class="actions" onclick="codepress2.toggleEditor()">turn on/off CodePress</button>\r
+       <button class="actions" onclick="codepress2.toggleLineNumbers()">show/hide line numbers</button>\r
+       <button class="actions" onclick="codepress2.toggleAutoComplete()">turn on/off auto-complete</button>\r
+       <button class="actions" onclick="codepress2.toggleReadOnly()">turn on/off read only</button>\r
+</p>\r
+\r
+\r
+\r
+<h3>Installation</h3>\r
+<ol>\r
+       <li>\r
+               <p>\r
+                       <a href="http://codepress.org/">Download</a> and uncompress CodePress under a directory inside your webserver.<br>\r
+                       Example:<strong> http://yourserver/codepress/</strong><br />\r
+                       Since CodePress is pure JavaScript and HTML, you can also test it without a webserver.\r
+               </p>\r
+       </li>\r
+       <li>\r
+               <p>\r
+                       Insert CodePress script somewhere in your page inside the <code>&lt;head&gt;</code> or above the <code>&lt;/body&gt;</code> tag.\r
+               </p>\r
+       \r
+               <p class="copycode">\r
+                       &lt;script src="/codepress/codepress.js" type="text/javascript"&gt;&lt;/script&gt;\r
+               </p>\r
+       </li>\r
+       \r
+       <li>\r
+               <p>\r
+                       Add the <code>&lt;textarea&gt;</code> tag to the place on your page you want CodePress to appear. CodePress will inherit the width and height of your textarea.\r
+                       When the page loads, it will automatically replace your textarea with a CodePress window.\r
+               </p>\r
+               <p class="copycode">\r
+                       &lt;textarea id="myCpWindow" class="codepress javascript linenumbers-off"&gt;<br />\r
+                       &nbsp;&nbsp;&nbsp;// your code here<br />\r
+                       &lt;/textarea&gt;\r
+               </p>\r
+               <ul>\r
+                       <li>\r
+                               The <code>javascript</code> portion of the class="" means that the language being edited is JavaScript.\r
+                       </li>\r
+                       <li>\r
+                               The <code>codepress</code> portion of the class="" is mandatory and indicates a textarea to be replaced for a CodePress window.\r
+                       </li>\r
+                       <li>\r
+                               Other class options are <code>linenumbers-off</code>, <code>autocomplete-off</code> and <code>readonly-on</code>.\r
+                       </li>                   \r
+                       <li>\r
+                               Careful not to use the same id for two different CodePress windows (<code>&lt;textarea id="<strong>xx</strong>"...&gt;</code>)\r
+                       </li>\r
+               </ul>\r
+\r
+       </li>\r
+</ol>\r
+\r
+<h3>You also can...</h3>\r
+<ol>\r
+       <li>\r
+               Open/edit code from a different textarea.<br />\r
+               Example: <code>textarea_id.edit('other_textarea_id','language')</code><br>\r
+       </li>\r
+       <li>\r
+               Get code from CodePress window.<br />\r
+               Example: <code>textarea_id.getCode()</code><br>\r
+       </li>\r
+       <li>\r
+               Turn on/off CodePress editor and return to the regular textarea.<br />\r
+               Example: <code>textarea_id.toggleEditor()</code><br>\r
+       </li>\r
+       <li>\r
+               Turn on/off line numbers.<br />\r
+               Example: <code>textarea_id.toggleLineNumbers()</code><br>\r
+       </li>\r
+       <li>\r
+               Turn on/off read only.<br />\r
+               Example: <code>textarea_id.toggleReadOnly()</code><br>\r
+       </li>\r
+       <li>\r
+               Turn on/off auto-complete.<br />\r
+               Example: <code>textarea_id.toggleAutoComplete()</code><br>\r
+       </li>\r
+       \r
+</ol>\r
+\r
+<!-- p>\r
+       You may want to use [id].getCode() to get the content code from CodePress window and save it to your server since CodePress only edit files and do not save them.\r
+</p>\r
+<p>\r
+       You may also want to open files from server. You'll have to write a server side script and replace the JavaScript call on codepress.js from codepress.html to codepress.php (if your server side language is PHP, of course).\r
+</p -->\r
+\r
+<h3>License</h3>\r
+<p>\r
+       CodePress is distributed under the <a href="http://www.opensource.org/licenses/lgpl-license.php">LGPL</a>. If your software is <a href="http://www.gnu.org/philosophy/license-list.html#GPLCompatibleLicenses">compatible</a> with this licence or it is under <a href="http://creativecommons.org/">Creative Commons</a>, you can use it as you want. Just keep the credits somewhere around.\r
+</p>\r
+\r
+\r
+</div><!--/container-->\r
+\r
+\r
+\r
+<!-- hidden codes for loading -->\r
+<textarea id="cp-php" class="hidden-code">\r
+<?php\r
+// Very simple implementation of server side script\r
+\r
+if(isset($_GET['file'])) {\r
+       $file = basename($_GET['file']);\r
+       $full_file = $path['server'].'/'.$path['webdocs'].'/'.$path['files']."/".$file;\r
+       if(file_exists($full_file)) {\r
+               $code = file_get_contents($full_file);\r
+               $code = preg_replace("/>/","&amp;gt;",$code);\r
+               $code = preg_replace("/</","&amp;lt;",$code);\r
+               $language = getLanguage($file);\r
+       }\r
+}\r
+?>\r
+\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html>\r
+<head>\r
+       <title>CodePress - Real Time Syntax Highlighting Editor written in JavaScript</title>\r
+       <link type="text/css" href="languages/codepress-<?=$language?>.css" rel="stylesheet" id="cp-lang-style" />\r
+       <script type="text/javascript" src="codepress.js"></script>\r
+       <script type="text/javascript">\r
+               CodePress.language = '<?=$language?>';\r
+       </script>\r
+</head>\r
+<body id="ffedt"><pre id="ieedt"><?=$code?></pre></body>\r
+</html>\r
+</textarea>\r
+\r
+<textarea id="cp-javascript" class="hidden-code">\r
+CodePress = function(obj) {\r
+       var self = document.createElement('iframe');\r
+       self.textarea = obj;\r
+       self.textarea.disabled = true;\r
+       self.style.height = self.textarea.clientHeight +'px';\r
+       self.style.width = self.textarea.clientWidth +'px';\r
+       \r
+       self.initialize = function() {\r
+               self.editor = self.contentWindow.CodePress;\r
+               self.editor.body = self.contentWindow.document.getElementsByTagName('body')[0];\r
+               self.editor.setCode(self.textarea.value);\r
+               self.editor.syntaxHighlight('init');\r
+       }\r
+       \r
+       self.edit = function(id,language) {\r
+               self.language = (language) ? language : self.textarea.className.replace(/ ?codepress ?/,'');\r
+               self.src = cpPath+'modules/codepress.html?engine='+self.getEngine()+'&language='+self.language;\r
+               if(self.attachEvent) self.attachEvent('onload',self.initialize);\r
+               else self.addEventListener('load',self.initialize,false);\r
+       }\r
+}\r
+</textarea>\r
+\r
+<textarea id="cp-autoit" class="hidden-code">\r
+#include\r
+IsNumber(15)\r
+@Macro\r
+;comment\r
+$var = "string"\r
+</textarea>\r
+\r
+<textarea id="cp-java" class="hidden-code">\r
+import java.io.FileFilter;\r
+import java.io.IOException;\r
+import java.io.PrintWriter;\r
+\r
+/**\r
+ * Project ECCO - File manager class\r
+ * @author Fernando M.A.d.S.\r
+ */\r
+public class FileManager extends HttpServlet {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+       private static String login = "feanndor"; // session var should come here\r
+       private static String usersPath = System.getProperty("user.dir")+File.separator+"htdocs"+File.separator+"ecco"+File.separator+"users"+File.separator;\r
+       private static File dir = new File(usersPath+login+File.separator);\r
+       static boolean existDirectories = false;\r
+       static int isDirectory = 0;\r
+\r
+       public FileFilter filterFiles(File dir) {\r
+               return (new FileFilter() {\r
+                       public boolean accept(File pathname) {\r
+                               return !(pathname.isDirectory());\r
+                       }\r
+               });\r
+       }\r
+}\r
+</textarea>\r
+\r
+<textarea id="cp-perl" class="hidden-code">\r
+#!/usr/bin/perl      \r
+# The first line of the script envokes Perl \r
+\r
+# Scalar variables\r
+$var1 = "Hello World";   \r
+$var2 = 14.6;\r
+\r
+# Array variables\r
+@arr1 = ("zero","one","two","three","four");\r
+\r
+# Hash variable, or associative array\r
+%hash1 = ("one","Monday","two", "Tuesday","three", "Wednesday","four","Thursday");\r
+\r
+# Some simple printing\r
+print $var1; \r
+\r
+# Subroutine\r
+sub test() {\r
+       print "ok";\r
+}\r
+</textarea>\r
+\r
+<textarea id="cp-sql" class="hidden-code">\r
+--\r
+-- simple select example\r
+-- \r
+SELECT * FROM books\r
+       WHERE price > 100.00 and price < 150.00\r
+       ORDER BY title\r
+\r
+SELECT books.title, count(*) AS Authors\r
+       FROM books\r
+       JOIN book_authors \r
+               ON books.book_number = book_authors.book_number\r
+       GROUP BY books.title\r
+\r
+-- insert, update and delete examples\r
+       \r
+INSERT INTO my_table (field1, field2, field3) VALUES ('test', 'N', NULL);\r
+\r
+BEGIN WORK;\r
+       UPDATE inventory SET quantity = quantity - 3 WHERE item = 'pants';\r
+COMMIT;\r
+</textarea>\r
+\r
+<textarea id="cp-html" class="hidden-code">\r
+<html>\r
+<head>\r
+       <title>CodePress - Online Real Time Syntax Highlighting Editor</title>\r
+\r
+       <style type="text/css">\r
+       @import url(styles.css);        \r
+       </style>\r
+       <script type="text/javascript">\r
+       function getCode() {\r
+               alert(textWithoutHighlighting);\r
+       }\r
+       </script>\r
+</head>\r
+<body>\r
+<div id="logo">\r
+       <h1><a href="http://codepress.org/">CodePress</a></h1>\r
+       <h2>Online Real Time Syntax Highlighting Editor</h2>\r
+       <img src="testimage.gif" />\r
+</div>\r
+<div id="languages">\r
+       <em>choose language:</em> \r
+       <button onclick="edit('codepress.php',this)" id="default">PHP</button> \r
+       <button onclick="edit('FileManager.java',this)">Java</button> \r
+</div>\r
+</body>\r
+</html>\r
+</textarea>\r
+\r
+<textarea id="cp-css" class="hidden-code">\r
+/* CSS comment */\r
+\r
+body {\r
+       color:#000;\r
+       background-color:white;\r
+       font:15px Georgia, "Lucida Grande", Arial, sans-serif; \r
+       letter-spacing:0.01em;\r
+       margin:15px;\r
+}\r
+\r
+p { \r
+       margin:0 0 15px 0; \r
+}\r
+\r
+a,a:visited {\r
+       color:#7f0055;\r
+}\r
+\r
+select {\r
+       background:#ffffe1;\r
+}\r
+\r
+h1 {\r
+       color:#7f0055;\r
+       margin:0;\r
+       padding:0;\r
+       font-size:42px;\r
+}\r
+</textarea>\r
+\r
+\r
+<script src="codepress.js" type="text/javascript"></script>\r
+</body>\r
+</html>\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/asp.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/asp.css
new file mode 100755 (executable)
index 0000000..87af390
--- /dev/null
@@ -0,0 +1,71 @@
+/*\r
+ * CodePress color styles for ASP-VB syntax highlighting\r
+ * By Martin D. Kirk\r
+ */\r
+/* tags */\r
+\r
+b {\r
+       color:#000080;\r
+} \r
+/* comments */\r
+big, big b, big em, big ins, big s, strong i, strong i b, strong i s, strong i u, strong i a, strong i a u, strong i s u {\r
+       color:gray;\r
+       font-weight:normal;\r
+}\r
+/* ASP comments */\r
+strong dfn, strong dfn a,strong dfn var, strong dfn a u, strong dfn u{\r
+       color:gray;\r
+       font-weight:normal;\r
+}\r
+ /* attributes */ \r
+s, s b, span s u, span s cite, strong span s {\r
+       color:#5656fa ;\r
+       font-weight:normal;\r
+}\r
+ /* strings */ \r
+strong s,strong s b, strong s u, strong s cite {\r
+       color:#009900;\r
+       font-weight:normal;\r
+}\r
+strong ins{\r
+       color:#000000;\r
+       font-weight:bold;\r
+}\r
+ /* Syntax */\r
+strong a, strong a u {\r
+       color:#0000FF;\r
+       font-weight:;\r
+}\r
+ /* Native Keywords */\r
+strong u {\r
+       color:#990099;\r
+       font-weight:bold;\r
+}\r
+/* Numbers */\r
+strong var{\r
+       color:#FF0000;\r
+}\r
+/* ASP Language */\r
+span{\r
+       color:#990000;\r
+       font-weight:bold;\r
+}\r
+strong i,strong a i, strong u i {\r
+       color:#009999;\r
+}\r
+/* style */\r
+em {\r
+       color:#800080;\r
+       font-style:normal;\r
+}\r
+ /* script */ \r
+ins {\r
+       color:#800000;\r
+       font-weight:bold;\r
+}\r
+\r
+/* <?php and ?> */\r
+cite, s cite {\r
+       color:red;\r
+       font-weight:bold;\r
+}
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/asp.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/asp.js
new file mode 100755 (executable)
index 0000000..7439539
--- /dev/null
@@ -0,0 +1,117 @@
+/*\r
+ * CodePress regular expressions for ASP-vbscript syntax highlighting\r
+ */\r
+\r
+// ASP VBScript\r
+Language.syntax = [\r
+// all tags\r
+       { input : /(&lt;[^!%|!%@]*?&gt;)/g, output : '<b>$1</b>' }, \r
+// style tags  \r
+       { input : /(&lt;style.*?&gt;)(.*?)(&lt;\/style&gt;)/g, output : '<em>$1</em><em>$2</em><em>$3</em>' }, \r
+// script tags \r
+       { input : /(&lt;script.*?&gt;)(.*?)(&lt;\/script&gt;)/g, output : '<ins>$1</ins><ins>$2</ins><ins>$3</ins>' }, \r
+// strings "" and attributes\r
+       { input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, \r
+// ASP Comment\r
+       { input : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<dfn>\'$1$2</dfn>'}, \r
+// <%.*\r
+       { input : /(&lt;%)/g, output : '<strong>$1' }, \r
+// .*%>        \r
+       { input : /(%&gt;)/g, output : '$1</strong>' }, \r
+// <%@...%>    \r
+       { input : /(&lt;%@)(.+?)(%&gt;)/gi, output : '$1<span>$2</span>$3' }, \r
+//Numbers      \r
+       { input : /\b([\d]+)\b/g, output : '<var>$1</var>' }, \r
+// Reserved Words 1 (Blue)\r
+       { input : /\b(And|As|ByRef|ByVal|Call|Case|Class|Const|Dim|Do|Each|Else|ElseIf|Empty|End|Eqv|Exit|False|For|Function)\b/gi, output : '<a>$1</a>' }, \r
+       { input : /\b(Get|GoTo|If|Imp|In|Is|Let|Loop|Me|Mod|Enum|New|Next|Not|Nothing|Null|On|Option|Or|Private|Public|ReDim|Rem)\b/gi, output : '<a>$1</a>' }, \r
+       { input : /\b(Resume|Select|Set|Stop|Sub|Then|To|True|Until|Wend|While|With|Xor|Execute|Randomize|Erase|ExecuteGlobal|Explicit|step)\b/gi, output : '<a>$1</a>' }, \r
+// Reserved Words 2 (Purple)   \r
+       { input : /\b(Abandon|Abs|AbsolutePage|AbsolutePosition|ActiveCommand|ActiveConnection|ActualSize|AddHeader|AddNew|AppendChunk)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(AppendToLog|Application|Array|Asc|Atn|Attributes|BeginTrans|BinaryRead|BinaryWrite|BOF|Bookmark|Boolean|Buffer|Byte)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(CacheControl|CacheSize|Cancel|CancelBatch|CancelUpdate|CBool|CByte|CCur|CDate|CDbl|Charset|Chr|CInt|Clear)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(ClientCertificate|CLng|Clone|Close|CodePage|CommandText|CommandType|CommandTimeout|CommitTrans|CompareBookmarks|ConnectionString|ConnectionTimeout)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(Contents|ContentType|Cookies|Cos|CreateObject|CreateParameter|CSng|CStr|CursorLocation|CursorType|DataMember|DataSource|Date|DateAdd|DateDiff)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(DatePart|DateSerial|DateValue|Day|DefaultDatabase|DefinedSize|Delete|Description|Double|EditMode|Eof|EOF|err|Error)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(Exp|Expires|ExpiresAbsolute|Filter|Find|Fix|Flush|Form|FormatCurrency|FormatDateTime|FormatNumber|FormatPercent)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(GetChunk|GetLastError|GetRows|GetString|Global|HelpContext|HelpFile|Hex|Hour|HTMLEncode|IgnoreCase|Index|InStr|InStrRev)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(Int|Integer|IsArray|IsClientConnected|IsDate|IsolationLevel|Join|LBound|LCase|LCID|Left|Len|Lock|LockType|Log|Long|LTrim)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(MapPath|MarshalOptions|MaxRecords|Mid|Minute|Mode|Month|MonthName|Move|MoveFirst|MoveLast|MoveNext|MovePrevious|Name|NextRecordset)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(Now|Number|NumericScale|ObjectContext|Oct|Open|OpenSchema|OriginalValue|PageCount|PageSize|Pattern|PICS|Precision|Prepared|Property)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(Provider|QueryString|RecordCount|Redirect|RegExp|Remove|RemoveAll|Replace|Requery|Request|Response|Resync|Right|Rnd)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(RollbackTrans|RTrim|Save|ScriptTimeout|Second|Seek|Server|ServerVariables|Session|SessionID|SetAbort|SetComplete|Sgn)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(Sin|Size|Sort|Source|Space|Split|Sqr|State|StaticObjects|Status|StayInSync|StrComp|String|StrReverse|Supports|Tan|Time)\b/gi, output : '<u>$1</u>' },\r
+       { input : /\b(Timeout|Timer|TimeSerial|TimeValue|TotalBytes|Transfer|Trim|Type|Type|UBound|UCase|UnderlyingValue|UnLock|Update|UpdateBatch)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(URLEncode|Value|Value|Version|Weekday|WeekdayName|Write|Year)\b/gi, output : '<u>$1</u>' }, \r
+// Reserved Words 3 (Turquis)\r
+       { input : /\b(vbBlack|vbRed|vbGreen|vbYellow|vbBlue|vbMagenta|vbCyan|vbWhite|vbBinaryCompare|vbTextCompare)\b/gi, output : '<i>$1</i>' }, \r
+       { input : /\b(vbSunday|vbMonday|vbTuesday|vbWednesday|vbThursday|vbFriday|vbSaturday|vbUseSystemDayOfWeek)\b/gi, output : '<i>$1</i>' }, \r
+       { input : /\b(vbFirstJan1|vbFirstFourDays|vbFirstFullWeek|vbGeneralDate|vbLongDate|vbShortDate|vbLongTime|vbShortTime)\b/gi, output : '<i>$1</i>' }, \r
+       { input : /\b(vbObjectError|vbCr|VbCrLf|vbFormFeed|vbLf|vbNewLine|vbNullChar|vbNullString|vbTab|vbVerticalTab|vbUseDefault|vbTrue)\b/gi, output : '<i>$1</i>' }, \r
+       { input : /\b(vbFalse|vbEmpty|vbNull|vbInteger|vbLong|vbSingle|vbDouble|vbCurrency|vbDate|vbString|vbObject|vbError|vbBoolean|vbVariant)\b/gi, output : '<i>$1</i>' }, \r
+       { input : /\b(vbDataObject|vbDecimal|vbByte|vbArray)\b/gi, output : '<i>$1</i>' },\r
+// html comments\r
+       { input : /(&lt;!--.*?--&gt.)/g, output : '<big>$1</big>' } \r
+]\r
+\r
+Language.Functions = [ \r
+       // Output at index 0, must be the desired tagname surrounding a $1\r
+       // Name is the index from the regex that marks the functionname\r
+       {input : /(function|sub)([ ]*?)(\w+)([ ]*?\()/gi , output : '<ins>$1</ins>', name : '$3'}\r
+]\r
+\r
+Language.snippets = [\r
+//Conditional\r
+       { input : 'if', output : 'If $0 Then\n\t\nEnd If' },\r
+       { input : 'ifelse', output : 'If $0 Then\n\t\n\nElse\n\t\nEnd If' },\r
+       { input : 'case', output : 'Select Case $0\n\tCase ?\n\tCase Else\nEnd Select'},\r
+//Response\r
+       { input : 'rw', output : 'Response.Write( $0 )' },\r
+       { input : 'resc', output : 'Response.Cookies( $0 )' },\r
+       { input : 'resb', output : 'Response.Buffer'},\r
+       { input : 'resflu', output : 'Response.Flush()'},\r
+       { input : 'resend', output : 'Response.End'},\r
+//Request\r
+       { input : 'reqc', output : 'Request.Cookies( $0 )' },\r
+       { input : 'rq', output : 'Request.Querystring("$0")' },\r
+       { input : 'rf', output : 'Request.Form("$0")' },\r
+//FSO\r
+       { input : 'fso', output : 'Set fso = Server.CreateObject("Scripting.FileSystemObject")\n$0' },\r
+       { input : 'setfo', output : 'Set fo = fso.getFolder($0)' },\r
+       { input : 'setfi', output : 'Set fi = fso.getFile($0)' },\r
+       { input : 'twr', output : 'Set f = fso.CreateTextFile($0,true)\'overwrite\nf.WriteLine()\nf.Close'},\r
+       { input : 'tre', output : 'Set f = fso.OpenTextFile($0, 1)\nf.ReadAll\nf.Close'},\r
+//Server\r
+       { input : 'mapp', output : 'Server.Mappath($0)' },\r
+//Loops\r
+       { input : 'foreach', output : 'For Each $0 in ?\n\t\nNext' },\r
+       { input : 'for', output : 'For $0 to ? step ?\n\t\nNext' },\r
+       { input : 'do', output : 'Do While($0)\n\t\nLoop' },\r
+       { input : 'untilrs', output : 'do until rs.eof\n\t\nrs.movenext\nloop' },\r
+//ADO\r
+       { input : 'adorec', output : 'Set rs = Server.CreateObject("ADODB.Recordset")' },\r
+       { input : 'adocon', output : 'Set Conn = Server.CreateObject("ADODB.Connection")' },\r
+       { input : 'adostr', output : 'Set oStr = Server.CreateObject("ADODB.Stream")' },\r
+//Http Request\r
+       { input : 'xmlhttp', output : 'Set xmlHttp = Server.CreateObject("Microsoft.XMLHTTP")\nxmlHttp.open("GET", $0, false)\nxmlHttp.send()\n?=xmlHttp.responseText' },\r
+       { input : 'xmldoc', output : 'Set xmldoc = Server.CreateObject("Microsoft.XMLDOM")\nxmldoc.async=false\nxmldoc.load(request)'},\r
+//Functions\r
+       { input : 'func', output : 'Function $0()\n\t\n\nEnd Function'},\r
+       { input : 'sub', output : 'Sub $0()\n\t\nEnd Sub'}\r
+\r
+]\r
+\r
+Language.complete = [\r
+       //{ input : '\'', output : '\'$0\'' },\r
+       { input : '"', output : '"$0"' },\r
+       { input : '(', output : '\($0\)' },\r
+       { input : '[', output : '\[$0\]' },\r
+       { input : '{', output : '{\n\t$0\n}' }          \r
+]\r
+\r
+Language.shortcuts = [\r
+       { input : '[space]', output : '&nbsp;' },\r
+       { input : '[enter]', output : '<br />' } ,\r
+       { input : '[j]', output : 'testing' },\r
+       { input : '[7]', output : '&amp;' }\r
+]
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/autoit.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/autoit.css
new file mode 100755 (executable)
index 0000000..953ed86
--- /dev/null
@@ -0,0 +1,13 @@
+/**\r
+ * CodePress color styles for AutoIt syntax highlighting\r
+ */\r
+\r
+u {font-style:normal;color:#000090;font-weight:bold;font-family:Monospace;}\r
+var {color:#AA0000;font-weight:bold;font-style:normal;}\r
+em {color:#FF33FF;}\r
+ins {color:#AC00A9;}\r
+i {color:#F000FF;}\r
+b {color:#FF0000;}\r
+a {color:#0080FF;font-weight:bold;}\r
+s, s u, s b {color:#9999CC;font-weight:normal;}\r
+cite, cite *{color:#009933;font-weight:normal;}
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/autoit.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/autoit.js
new file mode 100755 (executable)
index 0000000..c34ecc6
--- /dev/null
@@ -0,0 +1,32 @@
+/**\r
+ * CodePress regular expressions for AutoIt syntax highlighting\r
+ * @author: James Brooks, Michael HURNI\r
+ */ \r
\r
+// AutoIt \r
+Language.syntax = [  \r
+    { input : /({|}|\(|\))/g, output : '<b>$1</b>' }, // Brackets\r
+       { input : /(\*|\+|-)/g, output : '<b>$1</b>' }, // Operator\r
+       { input : /\"(.*?)(\"|<br>|<\/P>)/g, output : "<s>\"$1$2</s>" }, // strings double \r
+       { input : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<s>\'$1$2</s>' }, // strings single  \r
+       { input : /\b([\d]+)\b/g, output : '<ins>$1</ins>' }, // Numbers \r
+       { input : /#(.*?)(<br>|<\/P>)/g, output : '<i>#$1</i>$2' }, // Directives and Includes \r
+       { input : /(\$[\w\.]*)/g, output : '<var>$1</var>' }, // vars\r
+       { input : /(_[\w\.]*)/g, output : '<a>$1</a>' }, // underscored word\r
+       { input : /(\@[\w\.]*)/g, output : '<em>$1</em>' }, // Macros\r
+       { input : /\b(Abs|ACos|AdlibDisable|AdlibEnable|Asc|AscW|ASin|Assign|ATan|AutoItSetOption|AutoItWinGetTitle|AutoItWinSetTitle|Beep|Binary|BinaryLen|BinaryMid|BinaryToString|BitAND|BitNOT|BitOR|BitSHIFT|BitXOR|BlockInput|Break|Call|CDTray|Ceiling|Chr|ChrW|ClipGet|ClipPut|ConsoleRead|ConsoleWrite|ConsoleWriteError|ControlClick|ControlCommand|ControlDisable|ControlEnable|ControlFocus|ControlGetFocus|ControlGetHandle|ControlGetPos|ControlGetText|ControlHide|ControlListView|ControlMove|ControlSend|ControlSetText|ControlShow|Cos|Dec|DirCopy|DirCreate|DirGetSize|DirMove|DirRemove|DllCall|DllCall|DllClose|DllOpen|DllStructCreate|DllStructGetData|DllStructGetPtr|DllStructGetSize|DllStructSetData|DriveGetDrive|DriveGetFileSystem|DriveGetLabel|DriveGetSerial|DriveGetType|DriveMapAdd|DriveMapDel|DriveMapGet|DriveSetLabel|DriveSpaceFree|DriveSpaceTotal|DriveStatus|EnvGet|EnvSet|EnvUpdate|Eval|Execute|Exp|FileChangeDir|FileClose|FileCopy|FileCreateNTFS|FileCreateShortcut|FileDelete|FileExists|FileFindFirstFile|FileFindNextFile|FileGetAttrib|FileGetLongName|FileGetShortcut|FileGetShortName|FileGetSize|FileGetTime|FileGetVersion|FileInstall|FileMove|FileOpen|FileOpenDialog|FileRead|FileReadLine|FileRecycle|FileRecycleEmpty|FileSaveDialog|FileSelectFolder|FileSetAttrib|FileSetTime|FileWrite|FileWriteLine|Floor|FtpSetProxy|GuiCreate|GuiCtrlCreateAvi|GuiCtrlCreateButton|GuiCtrlCreateCheckbox|GuiCtrlCreateCombo|GuiCtrlCreateContextMenu|GuiCtrlCreateDate|GuiCtrlCreateDummy|GuiCtrlCreateEdit|GuiCtrlCreateGraphic|GuiCtrlCreateGroup|GuiCtrlCreateIcon|GuiCtrlCreateInput|GuiCtrlCreateLabel|GuiCtrlCreateList|GuiCtrlCreateListView|GuiCtrlCreateListViewItem|GuiCtrlCreateMenu|GuiCtrlCreateMenuItem|GuiCtrlCreateMonthCal|GuiCtrlCreateObj|GuiCtrlCreatePic|GuiCtrlCreateProgress|GuiCtrlCreateRadio|GuiCtrlCreateSlider|GuiCtrlCreateTab|GuiCtrlCreateTabItem|GuiCtrlCreateUpdown|GuiCtrlDelete|GuiCtrlGetHandle|GuiCtrlGetState|GuiCtrlRead|GuiCtrlRecvMsg|GuiCtrlSentMsg|GuiCtrlSendToDummy|GuiCtrlSetBkColor|GuiCtrlSetColor|GuiCtrlSetCursor|GuiCtrlSetData|GuiCtrlSetFont|GuiCtrlSetGraphic|GuiCtrlSetImage|GuiCtrlSetLimit|GuiCtrlSetOnEvent|GuiCtrlSetPos|GuiCtrlResizing|GuiCtrlSetState|GuiCtrlSetTip|GuiDelete|GuiGetCursorInfo|GuiGetMsg|GuiGetStyle|GuiRegisterMsg|GuiSetBkColor|GuiSetCoord|GuiSetCursor|GuiSetFont|GuiSetHelp|GuiSetIcon|GuiSetOnEvent|GuiSetStat|GuiSetStyle|GuiStartGroup|GuiSwitch|Hex|HotKeySet|HttpSetProxy|HWnd|InetGet|InetGetSize|IniDelete|IniRead|IniReadSection|IniReadSectionNames|IniRenameSection|IniWrite|IniWriteSection|InputBox|Int|IsAdmin|IsArray|IsBinary|IsBool|IsDeclared|IsDllStruct|IsFloat|IsHWnd|IsInt|IsKeyword|IsNumber|IsObj|IsString|Log|MemGetStats|Mod|MouseClick|MouseClickDrag|MouseDown|MouseGetCursor|MouseGetPos|MouseMove|MouseUp|MouseWheel|MsgBox|Number|ObjCreate|ObjEvent|ObjGet|ObjName|Ping|PixelCheckSum|PixelGetColor|PixelSearch|ProcessClose|ProcessExists|ProcessList|ProcessSetPriority|ProcessWait|ProcessWaitClose|ProgressOff|ProcessOn|ProgressSet|Random|RegDelete|RegEnumKey|RegEnumVal|RegRead|RegWrite|Round|Run|RunAsSet|RunWait|Send|SetError|SetExtended|ShellExecute|ShellExecuteWait|Shutdown|Sin|Sleep|SoundPlay|SoundSetWaveVolume|SplashImageOn|SplashOff|SplashTextOn|Sqrt|SRandom|StatusbarGetText|StderrRead|StdinWrite|StdoutRead|String|StringAddCR|StringCompare|StringFormat|StringInStr|StringIsAlNum|StringIsAlpha|StringIsASCII|StringIsDigit|StringIsFloat|StringIsInt|StringIsLower|StringIsSpace|StringIsUpper|StringIsXDigit|StringLeft|StringLen|StringLower|StringMid|StringRegExp|StringRegExpReplace|StringReplace|StringRight|StringSplit|StringStripCR|StringStripWS|StringToBinary|StringTrimLeft|StringTrimRight|StringUpper|Tan|TCPAccept|TCPCloseSocket|TCPConnect|TCPListen|TCPNameToIP|TCPrecv|TCPSend|TCPShutdown|TCPStartup|TimerDiff|TimerInit|ToolTip|TrayCreateItem|TrayCreateMenu|TrayGetMenu|TrayGetMsg|TrayItemDelete|TrayItemGetHandle|TrayItemGetState|TrayItemGetText|TrayItemSetOnEvent|TrayItemSetState|TrayItemSetText|TraySetClick|TraySetIcon|TraySetOnEvent|TraySetPauseIcon|TraySetState|TraySetToolTip|TrayTip|UBound|UDPBind|UDPCloseSocket|UDPOpen|UDPRecv|UDPSend|WinActivate|WinActive|WinClose|WinExists|WinFlash|WinGetCaretPos|WinGetClassList|WinGetClientSize|WinGetHandle|WinGetPos|WinGetProcess|WinGetState|WinGetText|WinGetTitle|WinKill|WinList|WinMenuSelectItem|WinMinimizeAll|WinMinimizeAllUndo|WinMove|WinSetOnTop|WinSetState|WinSetTitle|WinSetTrans|WinWait|WinWaitActive|WinWaitClose|WinWaitNotActive)\b/g, output : '<u>$1</u>' } ,// reserved words\r
+       { input : /\B;(.*?)(<br>|<\/P>)/g, output : '<cite>;$1</cite>$2' }, // comments \r
+       { input : /#CS(.*?)#CE/g, output : '<cite>#CS$1#CE</cite>' } // Block Comments\r
+] \r
\r
+Language.snippets = [] \r
\r
+Language.complete = [ \r
+{ input : '\'',output : '\'$0\'' }, \r
+{ input : '"', output : '"$0"' }, \r
+{ input : '(', output : '\($0\)' }, \r
+{ input : '[', output : '\[$0\]' }, \r
+{ input : '{', output : '{\n\t$0\n}' } \r
+] \r
\r
+Language.shortcuts = [] \r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/csharp.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/csharp.css
new file mode 100755 (executable)
index 0000000..6415d65
--- /dev/null
@@ -0,0 +1,9 @@
+/*\r
+ * CodePress color styles for Java syntax highlighting\r
+ * By Edwin de Jonge\r
+ */\r
+\r
+b {color:#7F0055;font-weight:bold;font-style:normal;} /* reserved words */\r
+a {color:#2A0088;font-weight:bold;font-style:normal;} /* types */\r
+i, i b, i s {color:#3F7F5F;font-weight:bold;} /* comments */\r
+s, s b {color:#2A00FF;font-weight:normal;} /* strings */
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/csharp.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/csharp.js
new file mode 100755 (executable)
index 0000000..20fdd91
--- /dev/null
@@ -0,0 +1,25 @@
+/*\r
+ * CodePress regular expressions for C# syntax highlighting\r
+ * By Edwin de Jonge\r
+ */\r
\r
+Language.syntax = [ // C#\r
+       { input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, // strings double quote\r
+       { input : /\'(.?)(\'|<br>|<\/P>)/g, output : '<s>\'$1$2</s>' }, // strings single quote \r
+       { input : /\b(abstract|as|base|break|case|catch|checked|continue|default|delegate|do|else|event|explicit|extern|false|finally|fixed|for|foreach|get|goto|if|implicit|in|interface|internal|is|lock|namespace|new|null|object|operator|out|override|params|partial|private|protected|public|readonly|ref|return|set|sealed|sizeof|static|stackalloc|switch|this|throw|true|try|typeof|unchecked|unsafe|using|value|virtual|while)\b/g, output : '<b>$1</b>' }, // reserved words\r
+       { input : /\b(bool|byte|char|class|double|float|int|interface|long|string|struct|void)\b/g, output : '<a>$1</a>' }, // types\r
+       { input : /([^:]|^)\/\/(.*?)(<br|<\/P)/g, output : '$1<i>//$2</i>$3' }, // comments //  \r
+       { input : /\/\*(.*?)\*\//g, output : '<i>/*$1*/</i>' } // comments /* */\r
+];\r
+\r
+Language.snippets = [];\r
+\r
+Language.complete = [ // Auto complete only for 1 character\r
+       {input : '\'',output : '\'$0\'' },\r
+       {input : '"', output : '"$0"' },\r
+       {input : '(', output : '\($0\)' },\r
+       {input : '[', output : '\[$0\]' },\r
+       {input : '{', output : '{\n\t$0\n}' }           \r
+];\r
+\r
+Language.shortcuts = [];
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/css.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/css.css
new file mode 100755 (executable)
index 0000000..64778d2
--- /dev/null
@@ -0,0 +1,10 @@
+/*\r
+ * CodePress color styles for CSS syntax highlighting\r
+ */\r
+\r
+b, b a, b u {color:#000080;} /* tags, ids, classes */\r
+i, i b, i s, i a, i u {color:gray;} /* comments */\r
+s, s b {color:#a0a0dd;} /* parameters */\r
+a {color:#0000ff;} /* keys */\r
+u {color:red;} /* values */\r
+\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/css.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/css.js
new file mode 100755 (executable)
index 0000000..00dcce0
--- /dev/null
@@ -0,0 +1,23 @@
+/*\r
+ * CodePress regular expressions for CSS syntax highlighting\r
+ */\r
+\r
+// CSS\r
+Language.syntax = [\r
+       { input : /(.*?){(.*?)}/g,output : '<b>$1</b>{<u>$2</u>}' }, // tags, ids, classes, values\r
+       { input : /([\w-]*?):([^\/])/g,output : '<a>$1</a>:$2' }, // keys\r
+       { input : /\((.*?)\)/g,output : '(<s>$1</s>)' }, // parameters\r
+       { input : /\/\*(.*?)\*\//g,output : '<i>/*$1*/</i>'} // comments\r
+]\r
+\r
+Language.snippets = []\r
+\r
+Language.complete = [\r
+       { input : '\'',output : '\'$0\'' },\r
+       { input : '"', output : '"$0"' },\r
+       { input : '(', output : '\($0\)' },\r
+       { input : '[', output : '\[$0\]' },\r
+       { input : '{', output : '{\n\t$0\n}' }          \r
+]\r
+\r
+Language.shortcuts = []\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/generic.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/generic.css
new file mode 100755 (executable)
index 0000000..3d52b6b
--- /dev/null
@@ -0,0 +1,9 @@
+/*\r
+ * CodePress color styles for generic syntax highlighting\r
+ */\r
+\r
+b {color:#7F0055;font-weight:bold;} /* reserved words */\r
+u {color:darkblue;font-weight:bold;} /* special words */\r
+i, i b, i s, i u, i em {color:green;font-weight:normal;} /* comments */\r
+s, s b, s em {color:#2A00FF;font-weight:normal;} /* strings */\r
+em {font-weight:bold;} /* special chars */
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/generic.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/generic.js
new file mode 100755 (executable)
index 0000000..8289da0
--- /dev/null
@@ -0,0 +1,25 @@
+/*\r
+ * CodePress regular expressions for generic syntax highlighting\r
+ */\r
\r
+// generic languages\r
+Language.syntax = [\r
+       { input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, // strings double quote\r
+       { input : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<s>\'$1$2</s>' }, // strings single quote\r
+       { input : /\b(abstract|continue|for|new|switch|default|goto|boolean|do|if|private|this|break|double|protected|throw|byte|else|import|public|throws|case|return|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|const|float|while|function|label)\b/g, output : '<b>$1</b>' }, // reserved words\r
+       { input : /([\(\){}])/g, output : '<em>$1</em>' }, // special chars;\r
+       { input : /([^:]|^)\/\/(.*?)(<br|<\/P)/g, output : '$1<i>//$2</i>$3' }, // comments //\r
+       { input : /\/\*(.*?)\*\//g, output : '<i>/*$1*/</i>' } // comments /* */\r
+]\r
+\r
+Language.snippets = []\r
+\r
+Language.complete = [\r
+       { input : '\'', output : '\'$0\'' },\r
+       { input : '"', output : '"$0"' },\r
+       { input : '(', output : '\($0\)' },\r
+       { input : '[', output : '\[$0\]' },\r
+       { input : '{', output : '{\n\t$0\n}' }          \r
+]\r
+\r
+Language.shortcuts = []\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/html.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/html.css
new file mode 100755 (executable)
index 0000000..35617cb
--- /dev/null
@@ -0,0 +1,13 @@
+/*\r
+ * CodePress color styles for HTML syntax highlighting\r
+ */\r
+\r
+b {color:#000080;} /* tags */\r
+ins, ins b, ins s, ins em {color:gray;} /* comments */\r
+s, s b {color:#7777e4;} /* attribute values */\r
+a {color:green;} /* links */\r
+u {color:#E67300;} /* forms */\r
+big {color:#db0000;} /* images */\r
+em, em b {color:#800080;} /* style */\r
+strong {color:#800000;} /* script */\r
+tt i {color:darkblue;font-weight:bold;} /* script reserved words */\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/html.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/html.js
new file mode 100755 (executable)
index 0000000..94469b4
--- /dev/null
@@ -0,0 +1,59 @@
+/*\r
+ * CodePress regular expressions for HTML syntax highlighting\r
+ */\r
+\r
+// HTML\r
+Language.syntax = [\r
+       { input : /(&lt;[^!]*?&gt;)/g, output : '<b>$1</b>'     }, // all tags\r
+       { input : /(&lt;a .*?&gt;|&lt;\/a&gt;)/g, output : '<a>$1</a>' }, // links\r
+       { input : /(&lt;img .*?&gt;)/g, output : '<big>$1</big>' }, // images\r
+       { input : /(&lt;\/?(button|textarea|form|input|select|option|label).*?&gt;)/g, output : '<u>$1</u>' }, // forms\r
+       { input : /(&lt;style.*?&gt;)(.*?)(&lt;\/style&gt;)/g, output : '<em>$1</em><em>$2</em><em>$3</em>' }, // style tags\r
+       { input : /(&lt;script.*?&gt;)(.*?)(&lt;\/script&gt;)/g, output : '<strong>$1</strong><tt>$2</tt><strong>$3</strong>' }, // script tags\r
+       { input : /=(".*?")/g, output : '=<s>$1</s>' }, // atributes double quote\r
+       { input : /=('.*?')/g, output : '=<s>$1</s>' }, // atributes single quote\r
+       { input : /(&lt;!--.*?--&gt.)/g, output : '<ins>$1</ins>' }, // comments \r
+       { input : /\b(alert|window|document|break|continue|do|for|new|this|void|case|default|else|function|return|typeof|while|if|label|switch|var|with|catch|boolean|int|try|false|throws|null|true|goto)\b/g, output : '<i>$1</i>' } // script reserved words \r
+]\r
+\r
+Language.snippets = [\r
+       { input : 'aref', output : '<a href="$0"></a>' },\r
+       { input : 'h1', output : '<h1>$0</h1>' },\r
+       { input : 'h2', output : '<h2>$0</h2>' },\r
+       { input : 'h3', output : '<h3>$0</h3>' },\r
+       { input : 'h4', output : '<h4>$0</h4>' },\r
+       { input : 'h5', output : '<h5>$0</h5>' },\r
+       { input : 'h6', output : '<h6>$0</h6>' },\r
+       { input : 'html', output : '<html>\n\t$0\n</html>' },\r
+       { input : 'head', output : '<head>\n\t<meta http-equiv="content-type" content="text/html; charset=utf-8" />\n\t<title>$0</title>\n\t\n</head>' },\r
+       { input : 'img', output : '<img src="$0" alt="" />' },\r
+       { input : 'input', output : '<input name="$0" id="" type="" value="" />' },\r
+       { input : 'label', output : '<label for="$0"></label>' },\r
+       { input : 'legend', output : '<legend>\n\t$0\n</legend>' },\r
+       { input : 'link', output : '<link rel="stylesheet" href="$0" type="text/css" media="screen" charset="utf-8" />' },              \r
+       { input : 'base', output : '<base href="$0" />' }, \r
+       { input : 'body', output : '<body>\n\t$0\n</body>' }, \r
+       { input : 'css', output : '<link rel="stylesheet" href="$0" type="text/css" media="screen" charset="utf-8" />' },\r
+       { input : 'div', output : '<div>\n\t$0\n</div>' },\r
+       { input : 'divid', output : '<div id="$0">\n\t\n</div>' },\r
+       { input : 'dl', output : '<dl>\n\t<dt>\n\t\t$0\n\t</dt>\n\t<dd></dd>\n</dl>' },\r
+       { input : 'fieldset', output : '<fieldset>\n\t$0\n</fieldset>' },\r
+       { input : 'form', output : '<form action="$0" method="" name="">\n\t\n</form>' },\r
+       { input : 'meta', output : '<meta name="$0" content="" />' },\r
+       { input : 'p', output : '<p>$0</p>' },\r
+       { input : 'script', output : '<script type="text/javascript" language="javascript" charset="utf-8">\n\t$0\t\n</script>' },\r
+       { input : 'scriptsrc', output : '<script src="$0" type="text/javascript" language="javascript" charset="utf-8"></script>' },\r
+       { input : 'span', output : '<span>$0</span>' },\r
+       { input : 'table', output : '<table border="$0" cellspacing="" cellpadding="">\n\t<tr><th></th></tr>\n\t<tr><td></td></tr>\n</table>' },\r
+       { input : 'style', output : '<style type="text/css" media="screen">\n\t$0\n</style>' }\r
+]\r
+       \r
+Language.complete = [\r
+       { input : '\'',output : '\'$0\'' },\r
+       { input : '"', output : '"$0"' },\r
+       { input : '(', output : '\($0\)' },\r
+       { input : '[', output : '\[$0\]' },\r
+       { input : '{', output : '{\n\t$0\n}' }          \r
+]\r
+\r
+Language.shortcuts = []\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/java.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/java.css
new file mode 100755 (executable)
index 0000000..2339ded
--- /dev/null
@@ -0,0 +1,7 @@
+/*\r
+ * CodePress color styles for Java syntax highlighting\r
+ */\r
+\r
+b {color:#7F0055;font-weight:bold;font-style:normal;} /* reserved words */\r
+i, i b, i s {color:#3F7F5F;font-weight:bold;} /* comments */\r
+s, s b {color:#2A00FF;font-weight:normal;} /* strings */\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/java.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/java.js
new file mode 100755 (executable)
index 0000000..61e9a06
--- /dev/null
@@ -0,0 +1,24 @@
+/*\r
+ * CodePress regular expressions for Java syntax highlighting\r
+ */\r
\r
+// Java\r
+Language.syntax = [\r
+       { input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>'}, // strings double quote\r
+       { input : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<s>\'$1$2</s>'}, // strings single quote\r
+       { input : /\b(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/g, output : '<b>$1</b>'}, // reserved words\r
+       { input : /([^:]|^)\/\/(.*?)(<br|<\/P)/g, output : '$1<i>//$2</i>$3'}, // comments //   \r
+       { input : /\/\*(.*?)\*\//g, output : '<i>/*$1*/</i>' }// comments /* */\r
+]\r
+\r
+Language.snippets = []\r
+\r
+Language.complete = [\r
+       { input : '\'',output : '\'$0\'' },\r
+       { input : '"', output : '"$0"' },\r
+       { input : '(', output : '\($0\)' },\r
+       { input : '[', output : '\[$0\]' },\r
+       { input : '{', output : '{\n\t$0\n}' }          \r
+]\r
+\r
+Language.shortcuts = []\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/javascript.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/javascript.css
new file mode 100755 (executable)
index 0000000..8cb9092
--- /dev/null
@@ -0,0 +1,8 @@
+/*\r
+ * CodePress color styles for JavaScript syntax highlighting\r
+ */\r
+\r
+b {color:#7F0055;font-weight:bold;} /* reserved words */\r
+u {color:darkblue;font-weight:bold;} /* special words */\r
+i, i b, i s, i u {color:green;font-weight:normal;} /* comments */\r
+s, s b, s u {color:#2A00FF;font-weight:normal;} /* strings */\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/javascript.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/javascript.js
new file mode 100755 (executable)
index 0000000..08cdea4
--- /dev/null
@@ -0,0 +1,30 @@
+/*\r
+ * CodePress regular expressions for JavaScript syntax highlighting\r
+ */\r
\r
+// JavaScript\r
+Language.syntax = [ \r
+       { input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, // strings double quote\r
+       { input : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<s>\'$1$2</s>' }, // strings single quote\r
+       { input : /\b(break|continue|do|for|new|this|void|case|default|else|function|return|typeof|while|if|label|switch|var|with|catch|boolean|int|try|false|throws|null|true|goto)\b/g, output : '<b>$1</b>' }, // reserved words\r
+       { input : /\b(alert|isNaN|parent|Array|parseFloat|parseInt|blur|clearTimeout|prompt|prototype|close|confirm|length|Date|location|Math|document|element|name|self|elements|setTimeout|navigator|status|String|escape|Number|submit|eval|Object|event|onblur|focus|onerror|onfocus|onclick|top|onload|toString|onunload|unescape|open|valueOf|window|onmouseover)\b/g, output : '<u>$1</u>' }, // special words\r
+       { input : /([^:]|^)\/\/(.*?)(<br|<\/P)/g, output : '$1<i>//$2</i>$3' }, // comments //\r
+       { input : /\/\*(.*?)\*\//g, output : '<i>/*$1*/</i>' } // comments /* */\r
+]\r
+\r
+Language.snippets = [\r
+       { input : 'dw', output : 'document.write(\'$0\');' },\r
+       { input : 'getid', output : 'document.getElementById(\'$0\')' },\r
+       { input : 'fun', output : 'function $0(){\n\t\n}' },\r
+       { input : 'func', output : 'function $0(){\n\t\n}' }\r
+]\r
+\r
+Language.complete = [\r
+       { input : '\'',output : '\'$0\'' },\r
+       { input : '"', output : '"$0"' },\r
+       { input : '(', output : '\($0\)' },\r
+       { input : '[', output : '\[$0\]' },\r
+       { input : '{', output : '{\n\t$0\n}' }          \r
+]\r
+\r
+Language.shortcuts = []\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/perl.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/perl.css
new file mode 100755 (executable)
index 0000000..d9bce85
--- /dev/null
@@ -0,0 +1,11 @@
+/*\r
+ * CodePress color styles for Perl syntax highlighting\r
+ * By J. Nick Koston\r
+ */\r
+\r
+b {color:#7F0055;font-weight:bold;} /* reserved words */\r
+i, i b, i s, i em, i a, i u {color:gray;font-weight:normal;} /* comments */\r
+s, s b, s a, s em, s u {color:#2A00FF;font-weight:normal;} /* strings */\r
+a {color:#006700;font-weight:bold;} /* variables */\r
+em {color:darkblue;font-weight:bold;} /* functions */\r
+u {font-weight:bold;} /* special chars */
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/perl.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/perl.js
new file mode 100755 (executable)
index 0000000..5026e5d
--- /dev/null
@@ -0,0 +1,27 @@
+/*\r
+ * CodePress regular expressions for Perl syntax highlighting\r
+ * By J. Nick Koston\r
+ */\r
+\r
+// Perl\r
+Language.syntax = [ \r
+       { input  : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, // strings double quote\r
+       { input  : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<s>\'$1$2</s>' }, // strings single quote\r
+       { input  : /([\$\@\%][\w\.]*)/g, output : '<a>$1</a>' }, // vars\r
+       { input  : /(sub\s+)([\w\.]*)/g, output : '$1<em>$2</em>' }, // functions\r
+       { input  : /\b(abs|accept|alarm|atan2|bind|binmode|bless|caller|chdir|chmod|chomp|chop|chown|chr|chroot|close|closedir|connect|continue|cos|crypt|dbmclose|dbmopen|defined|delete|die|do|dump|each|else|elsif|endgrent|endhostent|endnetent|endprotoent|endpwent|eof|eval|exec|exists|exit|fcntl|fileno|find|flock|for|foreach|fork|format|formlinegetc|getgrent|getgrgid|getgrnam|gethostbyaddr|gethostbyname|gethostent|getlogin|getnetbyaddr|getnetbyname|getnetent|getpeername|getpgrp|getppid|getpriority|getprotobyname|getprotobynumber|getprotoent|getpwent|getpwnam|getpwuid|getservbyaddr|getservbyname|getservbyport|getservent|getsockname|getsockopt|glob|gmtime|goto|grep|hex|hostname|if|import|index|int|ioctl|join|keys|kill|last|lc|lcfirst|length|link|listen|LoadExternals|local|localtime|log|lstat|map|mkdir|msgctl|msgget|msgrcv|msgsnd|my|next|no|oct|open|opendir|ordpack|package|pipe|pop|pos|print|printf|push|pwd|qq|quotemeta|qw|rand|read|readdir|readlink|recv|redo|ref|rename|require|reset|return|reverse|rewinddir|rindex|rmdir|scalar|seek|seekdir|select|semctl|semget|semop|send|setgrent|sethostent|setnetent|setpgrp|setpriority|setprotoent|setpwent|setservent|setsockopt|shift|shmctl|shmget|shmread|shmwrite|shutdown|sin|sleep|socket|socketpair|sort|splice|split|sprintf|sqrt|srand|stat|stty|study|sub|substr|symlink|syscall|sysopen|sysread|system|syswritetell|telldir|tie|tied|time|times|tr|truncate|uc|ucfirst|umask|undef|unless|unlink|until|unpack|unshift|untie|use|utime|values|vec|waitpid|wantarray|warn|while|write)\b/g, output : '<b>$1</b>' }, // reserved words\r
+       { input  : /([\(\){}])/g, output : '<u>$1</u>' }, // special chars\r
+       { input  : /#(.*?)(<br>|<\/P>)/g, output : '<i>#$1</i>$2' } // comments\r
+]\r
+\r
+Language.snippets = []\r
+\r
+Language.complete = [\r
+       { input : '\'',output : '\'$0\'' },\r
+       { input : '"', output : '"$0"' },\r
+       { input : '(', output : '\($0\)' },\r
+       { input : '[', output : '\[$0\]' },\r
+       { input : '{', output : '{\n\t$0\n}' }          \r
+]\r
+\r
+Language.shortcuts = []\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/php.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/php.css
new file mode 100755 (executable)
index 0000000..b20a35c
--- /dev/null
@@ -0,0 +1,12 @@
+/*\r
+ * CodePress color styles for PHP syntax highlighting\r
+ */\r
+\r
+b {color:#000080;} /* tags */\r
+big, big b, big em, big ins, big s, strong i, strong i b, strong i s, strong i u, strong i a, strong i a u, strong i s u {color:gray;font-weight:normal;} /* comments */\r
+s, s b, strong s u, strong s cite {color:#5656fa;font-weight:normal;} /* attributes and strings */\r
+strong a, strong a u {color:#006700;font-weight:bold;} /* variables */\r
+em {color:#800080;font-style:normal;} /* style */\r
+ins {color:#800000;} /* script */\r
+strong u {color:#7F0055;font-weight:bold;} /* reserved words */\r
+cite, s cite {color:red;font-weight:bold;} /* <?php and ?> */\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/php.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/php.js
new file mode 100755 (executable)
index 0000000..c7640ba
--- /dev/null
@@ -0,0 +1,61 @@
+/*\r
+ * CodePress regular expressions for PHP syntax highlighting\r
+ */\r
+\r
+// PHP\r
+Language.syntax = [\r
+       { input : /(&lt;[^!\?]*?&gt;)/g, output : '<b>$1</b>' }, // all tags\r
+       { input : /(&lt;style.*?&gt;)(.*?)(&lt;\/style&gt;)/g, output : '<em>$1</em><em>$2</em><em>$3</em>' }, // style tags\r
+       { input : /(&lt;script.*?&gt;)(.*?)(&lt;\/script&gt;)/g, output : '<ins>$1</ins><ins>$2</ins><ins>$3</ins>' }, // script tags\r
+       { input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, // strings double quote\r
+       { input : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<s>\'$1$2</s>'}, // strings single quote\r
+       { input : /(&lt;\?)/g, output : '<strong>$1' }, // <?.*\r
+       { input : /(\?&gt;)/g, output : '$1</strong>' }, // .*?>\r
+       { input : /(&lt;\?php|&lt;\?=|&lt;\?|\?&gt;)/g, output : '<cite>$1</cite>' }, // php tags\r
+       { input : /(\$[\w\.]*)/g, output : '<a>$1</a>' }, // vars\r
+       { input : /\b(false|true|and|or|xor|__FILE__|exception|__LINE__|array|as|break|case|class|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|for|foreach|function|global|if|include|include_once|isset|list|new|print|require|require_once|return|static|switch|unset|use|while|__FUNCTION__|__CLASS__|__METHOD__|final|php_user_filter|interface|implements|extends|public|private|protected|abstract|clone|try|catch|throw|this)\b/g, output : '<u>$1</u>' }, // reserved words\r
+       { input : /([^:])\/\/(.*?)(<br|<\/P)/g, output : '$1<i>//$2</i>$3' }, // php comments //\r
+       { input : /([^:])#(.*?)(<br|<\/P)/g, output : '$1<i>#$2</i>$3' }, // php comments #\r
+       { input : /\/\*(.*?)\*\//g, output : '<i>/*$1*/</i>' }, // php comments /* */\r
+       { input : /(&lt;!--.*?--&gt.)/g, output : '<big>$1</big>' } // html comments\r
+]\r
+\r
+Language.snippets = [\r
+       { input : 'if', output : 'if($0){\n\t\n}' },\r
+       { input : 'ifelse', output : 'if($0){\n\t\n}\nelse{\n\t\n}' },\r
+       { input : 'else', output : '}\nelse {\n\t' },\r
+       { input : 'elseif', output : '}\nelseif($0) {\n\t' },\r
+       { input : 'do', output : 'do{\n\t$0\n}\nwhile();' },\r
+       { input : 'inc', output : 'include_once("$0");' },\r
+       { input : 'fun', output : 'function $0(){\n\t\n}' },    \r
+       { input : 'func', output : 'function $0(){\n\t\n}' },   \r
+       { input : 'while', output : 'while($0){\n\t\n}' },\r
+       { input : 'for', output : 'for($0,,){\n\t\n}' },\r
+       { input : 'fore', output : 'foreach($0 as ){\n\t\n}' },\r
+       { input : 'foreach', output : 'foreach($0 as ){\n\t\n}' },\r
+       { input : 'echo', output : 'echo \'$0\';' },\r
+       { input : 'switch', output : 'switch($0) {\n\tcase "": break;\n\tdefault: ;\n}' },\r
+       { input : 'case', output : 'case "$0" : break;' },\r
+       { input : 'ret0', output : 'return false;' },\r
+       { input : 'retf', output : 'return false;' },\r
+       { input : 'ret1', output : 'return true;' },\r
+       { input : 'rett', output : 'return true;' },\r
+       { input : 'ret', output : 'return $0;' },\r
+       { input : 'def', output : 'define(\'$0\',\'\');' },\r
+       { input : '<?', output : 'php\n$0\n?>' }\r
+]\r
+\r
+Language.complete = [\r
+       { input : '\'', output : '\'$0\'' },\r
+       { input : '"', output : '"$0"' },\r
+       { input : '(', output : '\($0\)' },\r
+       { input : '[', output : '\[$0\]' },\r
+       { input : '{', output : '{\n\t$0\n}' }          \r
+]\r
+\r
+Language.shortcuts = [\r
+       { input : '[space]', output : '&nbsp;' },\r
+       { input : '[enter]', output : '<br />' } ,\r
+       { input : '[j]', output : 'testing' },\r
+       { input : '[7]', output : '&amp;' }\r
+]
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/ruby.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/ruby.css
new file mode 100755 (executable)
index 0000000..b23166b
--- /dev/null
@@ -0,0 +1,10 @@
+/*\r
+ * CodePress color styles for Ruby syntax highlighting\r
+ */\r
+\r
+b {color:#7F0055;font-weight:bold;} /* reserved words */\r
+i, i b, i s, i em, i a, i u {color:gray;font-weight:normal;} /* comments */\r
+s, s b, s a, s em, s u {color:#2A00FF;font-weight:normal;} /* strings */\r
+a {color:#006700;font-weight:bold;} /* variables */\r
+em {color:darkblue;font-weight:bold;} /* functions */\r
+u {font-weight:bold;} /* special chars */
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/ruby.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/ruby.js
new file mode 100755 (executable)
index 0000000..860f433
--- /dev/null
@@ -0,0 +1,26 @@
+/*\r
+ * CodePress regular expressions for Perl syntax highlighting\r
+ */\r
+\r
+// Ruby\r
+Language.syntax = [\r
+       { input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, // strings double quote \r
+       { input : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<s>\'$1$2</s>' }, // strings single quote\r
+       { input : /([\$\@\%]+)([\w\.]*)/g, output : '<a>$1$2</a>' }, // vars\r
+       { input : /(def\s+)([\w\.]*)/g, output : '$1<em>$2</em>' }, // functions\r
+       { input : /\b(alias|and|BEGIN|begin|break|case|class|def|defined|do|else|elsif|END|end|ensure|false|for|if|in|module|next|nil|not|or|redo|rescue|retry|return|self|super|then|true|undef|unless|until|when|while|yield)\b/g, output : '<b>$1</b>' }, // reserved words\r
+       { input  : /([\(\){}])/g, output : '<u>$1</u>' }, // special chars\r
+       { input  : /#(.*?)(<br>|<\/P>)/g, output : '<i>#$1</i>$2' } // comments\r
+];\r
+\r
+Language.snippets = []\r
+\r
+Language.complete = [\r
+       { input : '\'',output : '\'$0\'' },\r
+       { input : '"', output : '"$0"' },\r
+       { input : '(', output : '\($0\)' },\r
+       { input : '[', output : '\[$0\]' },\r
+       { input : '{', output : '{\n\t$0\n}' }          \r
+]\r
+\r
+Language.shortcuts = []\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/sql.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/sql.css
new file mode 100755 (executable)
index 0000000..17458c5
--- /dev/null
@@ -0,0 +1,10 @@
+/*\r
+ * CodePress color styles for SQL syntax highlighting\r
+ * By Merlin Moncure\r
+ */\r
\r
+b {color:#0000FF;font-style:normal;font-weight:bold;} /* reserved words */\r
+u {color:#FF0000;font-style:normal;} /* types */\r
+a {color:#CD6600;font-style:normal;font-weight:bold;} /* commands */\r
+i, i b, i u, i a, i s  {color:#A9A9A9;font-weight:normal;font-style:italic;} /* comments */\r
+s, s b, s u, s a, s i {color:#2A00FF;font-weight:normal;} /* strings */\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/sql.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/sql.js
new file mode 100755 (executable)
index 0000000..605c971
--- /dev/null
@@ -0,0 +1,30 @@
+/*\r
+ * CodePress regular expressions for SQL syntax highlighting\r
+ * By Merlin Moncure\r
+ */\r
\r
+// SQL\r
+Language.syntax = [\r
+       { input : /\'(.*?)(\')/g, output : '<s>\'$1$2</s>' }, // strings single quote\r
+       { input : /\b(add|after|aggregate|alias|all|and|as|authorization|between|by|cascade|cache|cache|called|case|check|column|comment|constraint|createdb|createuser|cycle|database|default|deferrable|deferred|diagnostics|distinct|domain|each|else|elseif|elsif|encrypted|except|exception|for|foreign|from|from|full|function|get|group|having|if|immediate|immutable|in|increment|initially|increment|index|inherits|inner|input|intersect|into|invoker|is|join|key|language|left|like|limit|local|loop|match|maxvalue|minvalue|natural|nextval|no|nocreatedb|nocreateuser|not|null|of|offset|oids|on|only|operator|or|order|outer|owner|partial|password|perform|plpgsql|primary|record|references|replace|restrict|return|returns|right|row|rule|schema|security|sequence|session|sql|stable|statistics|table|temp|temporary|then|time|to|transaction|trigger|type|unencrypted|union|unique|user|using|valid|value|values|view|volatile|when|where|with|without|zone)\b/gi, output : '<b>$1</b>' }, // reserved words\r
+       { input : /\b(bigint|bigserial|bit|boolean|box|bytea|char|character|cidr|circle|date|decimal|double|float4|float8|inet|int2|int4|int8|integer|interval|line|lseg|macaddr|money|numeric|oid|path|point|polygon|precision|real|refcursor|serial|serial4|serial8|smallint|text|timestamp|varbit|varchar)\b/gi, output : '<u>$1</u>' }, // types\r
+       { input : /\b(abort|alter|analyze|begin|checkpoint|close|cluster|comment|commit|copy|create|deallocate|declare|delete|drop|end|execute|explain|fetch|grant|insert|listen|load|lock|move|notify|prepare|reindex|reset|restart|revoke|rollback|select|set|show|start|truncate|unlisten|update)\b/gi, output : '<a>$1</a>' }, // commands\r
+       { input : /([^:]|^)\-\-(.*?)(<br|<\/P)/g, output: '$1<i>--$2</i>$3' } // comments //    \r
+]\r
+\r
+Language.snippets = [\r
+       { input : 'select', output : 'select $0 from  where ' }\r
+]\r
+\r
+Language.complete = [\r
+       { input : '\'', output : '\'$0\'' },\r
+       { input : '"', output : '"$0"' },\r
+       { input : '(', output : '\($0\)' },\r
+       { input : '[', output : '\[$0\]' },\r
+       { input : '{', output : '{\n\t$0\n}' }          \r
+]\r
+\r
+Language.shortcuts = []\r
+\r
+\r
+\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/text.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/text.css
new file mode 100755 (executable)
index 0000000..8e5ba28
--- /dev/null
@@ -0,0 +1,5 @@
+/*\r
+ * CodePress color styles for Text syntax highlighting\r
+ */\r
+\r
+/* do nothing as expected */\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/text.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/text.js
new file mode 100755 (executable)
index 0000000..1895430
--- /dev/null
@@ -0,0 +1,9 @@
+/*\r
+ * CodePress regular expressions for Text syntax highlighting\r
+ */\r
+\r
+// plain text\r
+Language.syntax = []\r
+Language.snippets = []\r
+Language.complete = []\r
+Language.shortcuts = []\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/vbscript.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/vbscript.css
new file mode 100755 (executable)
index 0000000..d65663b
--- /dev/null
@@ -0,0 +1,71 @@
+/*\r
+ * CodePress color styles for ASP-VB syntax highlighting \r
+ * By Martin D. Kirk\r
+ */\r
+\r
+/* tags */\r
+b {\r
+       color:#000080;\r
+} \r
+/* comments */\r
+big, big b, big em, big ins, big s, strong i, strong i b, strong i s, strong i u, strong i a, strong i a u, strong i s u {\r
+       color:gray;\r
+       font-weight:normal;\r
+}\r
+/* ASP comments */\r
+strong dfn, strong dfn a,strong dfn var, strong dfn a u, strong dfn u{\r
+       color:gray;\r
+       font-weight:normal;\r
+}\r
+ /* attributes */ \r
+s, s b, span s u, span s cite, strong span s {\r
+       color:#5656fa ;\r
+       font-weight:normal;\r
+}\r
+ /* strings */ \r
+strong s,strong s b, strong s u, strong s cite {\r
+       color:#009900;\r
+       font-weight:normal;\r
+}\r
+strong ins{\r
+       color:#000000;\r
+       font-weight:bold;\r
+}\r
+ /* Syntax */\r
+strong a, strong a u {\r
+       color:#0000FF;\r
+       font-weight:;\r
+}\r
+ /* Native Keywords */\r
+strong u {\r
+       color:#990099;\r
+       font-weight:bold;\r
+}\r
+/* Numbers */\r
+strong var{\r
+       color:#FF0000;\r
+}\r
+/* ASP Language */\r
+span{\r
+       color:#990000;\r
+       font-weight:bold;\r
+}\r
+strong i,strong a i, strong u i {\r
+       color:#009999;\r
+}\r
+/* style */\r
+em {\r
+       color:#800080;\r
+       font-style:normal;\r
+}\r
+ /* script */ \r
+ins {\r
+       color:#800000;\r
+       font-weight:bold;\r
+}\r
+\r
+/* <?php and ?> */\r
+cite, s cite {\r
+       color:red;\r
+       font-weight:bold;\r
+}
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/vbscript.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/vbscript.js
new file mode 100755 (executable)
index 0000000..7439539
--- /dev/null
@@ -0,0 +1,117 @@
+/*\r
+ * CodePress regular expressions for ASP-vbscript syntax highlighting\r
+ */\r
+\r
+// ASP VBScript\r
+Language.syntax = [\r
+// all tags\r
+       { input : /(&lt;[^!%|!%@]*?&gt;)/g, output : '<b>$1</b>' }, \r
+// style tags  \r
+       { input : /(&lt;style.*?&gt;)(.*?)(&lt;\/style&gt;)/g, output : '<em>$1</em><em>$2</em><em>$3</em>' }, \r
+// script tags \r
+       { input : /(&lt;script.*?&gt;)(.*?)(&lt;\/script&gt;)/g, output : '<ins>$1</ins><ins>$2</ins><ins>$3</ins>' }, \r
+// strings "" and attributes\r
+       { input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, \r
+// ASP Comment\r
+       { input : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<dfn>\'$1$2</dfn>'}, \r
+// <%.*\r
+       { input : /(&lt;%)/g, output : '<strong>$1' }, \r
+// .*%>        \r
+       { input : /(%&gt;)/g, output : '$1</strong>' }, \r
+// <%@...%>    \r
+       { input : /(&lt;%@)(.+?)(%&gt;)/gi, output : '$1<span>$2</span>$3' }, \r
+//Numbers      \r
+       { input : /\b([\d]+)\b/g, output : '<var>$1</var>' }, \r
+// Reserved Words 1 (Blue)\r
+       { input : /\b(And|As|ByRef|ByVal|Call|Case|Class|Const|Dim|Do|Each|Else|ElseIf|Empty|End|Eqv|Exit|False|For|Function)\b/gi, output : '<a>$1</a>' }, \r
+       { input : /\b(Get|GoTo|If|Imp|In|Is|Let|Loop|Me|Mod|Enum|New|Next|Not|Nothing|Null|On|Option|Or|Private|Public|ReDim|Rem)\b/gi, output : '<a>$1</a>' }, \r
+       { input : /\b(Resume|Select|Set|Stop|Sub|Then|To|True|Until|Wend|While|With|Xor|Execute|Randomize|Erase|ExecuteGlobal|Explicit|step)\b/gi, output : '<a>$1</a>' }, \r
+// Reserved Words 2 (Purple)   \r
+       { input : /\b(Abandon|Abs|AbsolutePage|AbsolutePosition|ActiveCommand|ActiveConnection|ActualSize|AddHeader|AddNew|AppendChunk)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(AppendToLog|Application|Array|Asc|Atn|Attributes|BeginTrans|BinaryRead|BinaryWrite|BOF|Bookmark|Boolean|Buffer|Byte)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(CacheControl|CacheSize|Cancel|CancelBatch|CancelUpdate|CBool|CByte|CCur|CDate|CDbl|Charset|Chr|CInt|Clear)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(ClientCertificate|CLng|Clone|Close|CodePage|CommandText|CommandType|CommandTimeout|CommitTrans|CompareBookmarks|ConnectionString|ConnectionTimeout)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(Contents|ContentType|Cookies|Cos|CreateObject|CreateParameter|CSng|CStr|CursorLocation|CursorType|DataMember|DataSource|Date|DateAdd|DateDiff)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(DatePart|DateSerial|DateValue|Day|DefaultDatabase|DefinedSize|Delete|Description|Double|EditMode|Eof|EOF|err|Error)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(Exp|Expires|ExpiresAbsolute|Filter|Find|Fix|Flush|Form|FormatCurrency|FormatDateTime|FormatNumber|FormatPercent)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(GetChunk|GetLastError|GetRows|GetString|Global|HelpContext|HelpFile|Hex|Hour|HTMLEncode|IgnoreCase|Index|InStr|InStrRev)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(Int|Integer|IsArray|IsClientConnected|IsDate|IsolationLevel|Join|LBound|LCase|LCID|Left|Len|Lock|LockType|Log|Long|LTrim)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(MapPath|MarshalOptions|MaxRecords|Mid|Minute|Mode|Month|MonthName|Move|MoveFirst|MoveLast|MoveNext|MovePrevious|Name|NextRecordset)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(Now|Number|NumericScale|ObjectContext|Oct|Open|OpenSchema|OriginalValue|PageCount|PageSize|Pattern|PICS|Precision|Prepared|Property)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(Provider|QueryString|RecordCount|Redirect|RegExp|Remove|RemoveAll|Replace|Requery|Request|Response|Resync|Right|Rnd)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(RollbackTrans|RTrim|Save|ScriptTimeout|Second|Seek|Server|ServerVariables|Session|SessionID|SetAbort|SetComplete|Sgn)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(Sin|Size|Sort|Source|Space|Split|Sqr|State|StaticObjects|Status|StayInSync|StrComp|String|StrReverse|Supports|Tan|Time)\b/gi, output : '<u>$1</u>' },\r
+       { input : /\b(Timeout|Timer|TimeSerial|TimeValue|TotalBytes|Transfer|Trim|Type|Type|UBound|UCase|UnderlyingValue|UnLock|Update|UpdateBatch)\b/gi, output : '<u>$1</u>' }, \r
+       { input : /\b(URLEncode|Value|Value|Version|Weekday|WeekdayName|Write|Year)\b/gi, output : '<u>$1</u>' }, \r
+// Reserved Words 3 (Turquis)\r
+       { input : /\b(vbBlack|vbRed|vbGreen|vbYellow|vbBlue|vbMagenta|vbCyan|vbWhite|vbBinaryCompare|vbTextCompare)\b/gi, output : '<i>$1</i>' }, \r
+       { input : /\b(vbSunday|vbMonday|vbTuesday|vbWednesday|vbThursday|vbFriday|vbSaturday|vbUseSystemDayOfWeek)\b/gi, output : '<i>$1</i>' }, \r
+       { input : /\b(vbFirstJan1|vbFirstFourDays|vbFirstFullWeek|vbGeneralDate|vbLongDate|vbShortDate|vbLongTime|vbShortTime)\b/gi, output : '<i>$1</i>' }, \r
+       { input : /\b(vbObjectError|vbCr|VbCrLf|vbFormFeed|vbLf|vbNewLine|vbNullChar|vbNullString|vbTab|vbVerticalTab|vbUseDefault|vbTrue)\b/gi, output : '<i>$1</i>' }, \r
+       { input : /\b(vbFalse|vbEmpty|vbNull|vbInteger|vbLong|vbSingle|vbDouble|vbCurrency|vbDate|vbString|vbObject|vbError|vbBoolean|vbVariant)\b/gi, output : '<i>$1</i>' }, \r
+       { input : /\b(vbDataObject|vbDecimal|vbByte|vbArray)\b/gi, output : '<i>$1</i>' },\r
+// html comments\r
+       { input : /(&lt;!--.*?--&gt.)/g, output : '<big>$1</big>' } \r
+]\r
+\r
+Language.Functions = [ \r
+       // Output at index 0, must be the desired tagname surrounding a $1\r
+       // Name is the index from the regex that marks the functionname\r
+       {input : /(function|sub)([ ]*?)(\w+)([ ]*?\()/gi , output : '<ins>$1</ins>', name : '$3'}\r
+]\r
+\r
+Language.snippets = [\r
+//Conditional\r
+       { input : 'if', output : 'If $0 Then\n\t\nEnd If' },\r
+       { input : 'ifelse', output : 'If $0 Then\n\t\n\nElse\n\t\nEnd If' },\r
+       { input : 'case', output : 'Select Case $0\n\tCase ?\n\tCase Else\nEnd Select'},\r
+//Response\r
+       { input : 'rw', output : 'Response.Write( $0 )' },\r
+       { input : 'resc', output : 'Response.Cookies( $0 )' },\r
+       { input : 'resb', output : 'Response.Buffer'},\r
+       { input : 'resflu', output : 'Response.Flush()'},\r
+       { input : 'resend', output : 'Response.End'},\r
+//Request\r
+       { input : 'reqc', output : 'Request.Cookies( $0 )' },\r
+       { input : 'rq', output : 'Request.Querystring("$0")' },\r
+       { input : 'rf', output : 'Request.Form("$0")' },\r
+//FSO\r
+       { input : 'fso', output : 'Set fso = Server.CreateObject("Scripting.FileSystemObject")\n$0' },\r
+       { input : 'setfo', output : 'Set fo = fso.getFolder($0)' },\r
+       { input : 'setfi', output : 'Set fi = fso.getFile($0)' },\r
+       { input : 'twr', output : 'Set f = fso.CreateTextFile($0,true)\'overwrite\nf.WriteLine()\nf.Close'},\r
+       { input : 'tre', output : 'Set f = fso.OpenTextFile($0, 1)\nf.ReadAll\nf.Close'},\r
+//Server\r
+       { input : 'mapp', output : 'Server.Mappath($0)' },\r
+//Loops\r
+       { input : 'foreach', output : 'For Each $0 in ?\n\t\nNext' },\r
+       { input : 'for', output : 'For $0 to ? step ?\n\t\nNext' },\r
+       { input : 'do', output : 'Do While($0)\n\t\nLoop' },\r
+       { input : 'untilrs', output : 'do until rs.eof\n\t\nrs.movenext\nloop' },\r
+//ADO\r
+       { input : 'adorec', output : 'Set rs = Server.CreateObject("ADODB.Recordset")' },\r
+       { input : 'adocon', output : 'Set Conn = Server.CreateObject("ADODB.Connection")' },\r
+       { input : 'adostr', output : 'Set oStr = Server.CreateObject("ADODB.Stream")' },\r
+//Http Request\r
+       { input : 'xmlhttp', output : 'Set xmlHttp = Server.CreateObject("Microsoft.XMLHTTP")\nxmlHttp.open("GET", $0, false)\nxmlHttp.send()\n?=xmlHttp.responseText' },\r
+       { input : 'xmldoc', output : 'Set xmldoc = Server.CreateObject("Microsoft.XMLDOM")\nxmldoc.async=false\nxmldoc.load(request)'},\r
+//Functions\r
+       { input : 'func', output : 'Function $0()\n\t\n\nEnd Function'},\r
+       { input : 'sub', output : 'Sub $0()\n\t\nEnd Sub'}\r
+\r
+]\r
+\r
+Language.complete = [\r
+       //{ input : '\'', output : '\'$0\'' },\r
+       { input : '"', output : '"$0"' },\r
+       { input : '(', output : '\($0\)' },\r
+       { input : '[', output : '\[$0\]' },\r
+       { input : '{', output : '{\n\t$0\n}' }          \r
+]\r
+\r
+Language.shortcuts = [\r
+       { input : '[space]', output : '&nbsp;' },\r
+       { input : '[enter]', output : '<br />' } ,\r
+       { input : '[j]', output : 'testing' },\r
+       { input : '[7]', output : '&amp;' }\r
+]
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/xsl.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/xsl.css
new file mode 100755 (executable)
index 0000000..32634b6
--- /dev/null
@@ -0,0 +1,15 @@
+/*\r
+ * CodePress color styles for HTML syntax highlighting\r
+ * By RJ Bruneel\r
+ */\r
\r
+b {color:#000080;} /* tags */\r
+ins, ins b, ins s, ins em {color:gray;} /* comments */\r
+s, s b {color:#7777e4;} /* attribute values */\r
+a {color:#E67300;} /* links */\r
+u {color:#CC66CC;} /* forms */\r
+big {color:#db0000;} /* images */\r
+em, em b {color:#800080;} /* style */\r
+strong {color:#800000;} /* script */\r
+tt i {color:darkblue;font-weight:bold;} /* script reserved words */\r
+xsl {color:green;} /* xsl */\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/xsl.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/languages/xsl.js
new file mode 100755 (executable)
index 0000000..b23d359
--- /dev/null
@@ -0,0 +1,103 @@
+/*\r
+ * CodePress regular expressions for XSL syntax highlighting\r
+ * By RJ Bruneel\r
+ */\r
+\r
+Language.syntax = [ // XSL\r
+       {\r
+       input : /(&lt;[^!]*?&gt;)/g,\r
+       output : '<b>$1</b>' // all tags\r
+       },{\r
+       input : /(&lt;a.*?&gt;|&lt;\/a&gt;)/g,\r
+       output : '<a>$1</a>' // links\r
+       },{\r
+       input : /(&lt;img .*?&gt;)/g,\r
+       output : '<big>$1</big>' // images\r
+       },{\r
+       input : /(&lt;\/?(button|textarea|form|input|select|option|label).*?&gt;)/g,\r
+       output : '<u>$1</u>' // forms\r
+       },{\r
+       input : /(&lt;style.*?&gt;)(.*?)(&lt;\/style&gt;)/g,\r
+       output : '<em>$1</em><em>$2</em><em>$3</em>' // style tags\r
+       },{\r
+       input : /(&lt;script.*?&gt;)(.*?)(&lt;\/script&gt;)/g,\r
+       output : '<strong>$1</strong><tt>$2</tt><strong>$3</strong>' // script tags\r
+       },{     \r
+       input : /(&lt;xsl.*?&gt;|&lt;\/xsl.*?&gt;)/g,\r
+       output : '<xsl>$1</xsl>' // xsl\r
+       },{\r
+       input : /=(".*?")/g,\r
+       output : '=<s>$1</s>' // atributes double quote\r
+       },{\r
+       input : /=('.*?')/g,\r
+       output : '=<s>$1</s>' // atributes single quote\r
+       },{\r
+       input : /(&lt;!--.*?--&gt.)/g,\r
+       output : '<ins>$1</ins>' // comments \r
+       },{\r
+       input : /\b(alert|window|document|break|continue|do|for|new|this|void|case|default|else|function|return|typeof|while|if|label|switch|var|with|catch|boolean|int|try|false|throws|null|true|goto)\b/g,\r
+       output : '<i>$1</i>' // script reserved words\r
+       }\r
+];\r
+\r
+Language.snippets = [\r
+       {input : 'aref', output : '<a href="$0"></a>' },\r
+       {input : 'h1', output : '<h1>$0</h1>' },\r
+       {input : 'h2', output : '<h2>$0</h2>' },\r
+       {input : 'h3', output : '<h3>$0</h3>' },\r
+       {input : 'h4', output : '<h4>$0</h4>' },\r
+       {input : 'h5', output : '<h5>$0</h5>' },\r
+       {input : 'h6', output : '<h6>$0</h6>' },\r
+       {input : 'html', output : '<html>\n\t$0\n</html>' },\r
+       {input : 'head', output : '<head>\n\t<meta http-equiv="content-type" content="text/html; charset=utf-8" />\n\t<title>$0</title>\n\t\n</head>' },\r
+       {input : 'img', output : '<img src="$0" width="" height="" alt="" border="0" />' },\r
+       {input : 'input', output : '<input name="$0" id="" type="" value="" />' },\r
+       {input : 'label', output : '<label for="$0"></label>' },\r
+       {input : 'legend', output : '<legend>\n\t$0\n</legend>' },\r
+       {input : 'link', output : '<link rel="stylesheet" href="$0" type="text/css" media="screen" charset="utf-8" />' },               \r
+       {input : 'base', output : '<base href="$0" />' }, \r
+       {input : 'body', output : '<body>\n\t$0\n</body>' }, \r
+       {input : 'css', output : '<link rel="stylesheet" href="$0" type="text/css" media="screen" charset="utf-8" />' },\r
+       {input : 'div', output : '<div>\n\t$0\n</div>' },\r
+       {input : 'divid', output : '<div id="$0">\n\t\n</div>' },\r
+       {input : 'dl', output : '<dl>\n\t<dt>\n\t\t$0\n\t</dt>\n\t<dd></dd>\n</dl>' },\r
+       {input : 'fieldset', output : '<fieldset>\n\t$0\n</fieldset>' },\r
+       {input : 'form', output : '<form action="$0" method="" name="">\n\t\n</form>' },\r
+       {input : 'meta', output : '<meta name="$0" content="" />' },\r
+       {input : 'p', output : '<p>$0</p>' },\r
+       {input : 'b', output : '<b>$0</b>' },\r
+       {input : 'li', output : '<li>$0</li>' },\r
+       {input : 'ul', output : '<ul>$0</ul>' },\r
+       {input : 'ol', output : '<ol>$0</ol>' },\r
+       {input : 'strong', output : '<strong>$0</strong>' },\r
+       {input : 'br', output : '<br />' },\r
+       {input : 'script', output : '<script type="text/javascript" language="javascript" charset="utf-8">\n\t$0\t\n</script>' },\r
+       {input : 'scriptsrc', output : '<script src="$0" type="text/javascript" language="javascript" charset="utf-8"></script>' },\r
+       {input : 'span', output : '<span>$0</span>' },\r
+       {input : 'table', output : '<table border="$0" cellspacing="" cellpadding="">\n\t<tr><th></th></tr>\n\t<tr><td></td></tr>\n</table>' },\r
+       {input : 'style', output : '<style type="text/css" media="screen">\n\t$0\n</style>' },\r
+       {input : 'xsl:stylesheet', output : '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">' },\r
+       {input : 'xsl:template', output : '<xsl:template>$0</xsl:template>' },\r
+       {input : 'xsl:for-each', output : '<xsl:for-each select="$0"></xsl:for-each>' },\r
+       {input : 'xsl:choose', output : '<xsl:choose>$0<\xsl:choose>' },\r
+       {input : 'xsl:param', output : '<xsl:param name="$0" />' },\r
+       {input : 'xsl:variable', output : '<xsl:variable name="$0"></xsl:variable>' },\r
+       {input : 'xsl:if', output : '<xsl:if test="$0"></xsl:if>' },\r
+       {input : 'xsl:when', output : '<xsl:when test="$0"></xsl:when>' },\r
+       {input : 'xsl:otherwise', output : '<xsl:otherwise>$0</xsl:otherwise>' },\r
+       {input : 'xsl:attribute', output : '<xsl:attribute name="$0"></xsl:attribute>' },\r
+       {input : 'xsl:value-of', output : '<xsl:value-of select="$0"/>' },\r
+       {input : 'xsl:with-param', output : '<xsl:with-param name="$0" select="" />' },\r
+       {input : 'xsl:call-template', output : '<xsl:call-template name="$0">' }\r
+\r
+];\r
+       \r
+Language.complete = [ // Auto complete only for 1 character\r
+       {input : '\'',output : '\'$0\'' },\r
+       {input : '"', output : '"$0"' },\r
+       {input : '(', output : '\($0\)' },\r
+       {input : '[', output : '\[$0\]' },\r
+       {input : '{', output : '{\n\t$0\n}' }           \r
+];\r
+\r
+Language.shortcuts = [];
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/license.txt b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress-0.9.6/license.txt
new file mode 100755 (executable)
index 0000000..81b55d9
--- /dev/null
@@ -0,0 +1,458 @@
+                 GNU LESSER GENERAL PUBLIC LICENSE\r
+                      Version 2.1, February 1999\r
+\r
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.\r
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ Everyone is permitted to copy and distribute verbatim copies\r
+ of this license document, but changing it is not allowed.\r
+\r
+[This is the first released version of the Lesser GPL.  It also counts\r
+ as the successor of the GNU Library Public License, version 2, hence\r
+ the version number 2.1.]\r
+\r
+                           Preamble\r
+\r
+  The licenses for most software are designed to take away your\r
+freedom to share and change it.  By contrast, the GNU General Public\r
+Licenses are intended to guarantee your freedom to share and change\r
+free software--to make sure the software is free for all its users.\r
+\r
+  This license, the Lesser General Public License, applies to some\r
+specially designated software packages--typically libraries--of the\r
+Free Software Foundation and other authors who decide to use it.  You\r
+can use it too, but we suggest you first think carefully about whether\r
+this license or the ordinary General Public License is the better\r
+strategy to use in any particular case, based on the explanations below.\r
+\r
+  When we speak of free software, we are referring to freedom of use,\r
+not price.  Our General Public Licenses are designed to make sure that\r
+you have the freedom to distribute copies of free software (and charge\r
+for this service if you wish); that you receive source code or can get\r
+it if you want it; that you can change the software and use pieces of\r
+it in new free programs; and that you are informed that you can do\r
+these things.\r
+\r
+  To protect your rights, we need to make restrictions that forbid\r
+distributors to deny you these rights or to ask you to surrender these\r
+rights.  These restrictions translate to certain responsibilities for\r
+you if you distribute copies of the library or if you modify it.\r
+\r
+  For example, if you distribute copies of the library, whether gratis\r
+or for a fee, you must give the recipients all the rights that we gave\r
+you.  You must make sure that they, too, receive or can get the source\r
+code.  If you link other code with the library, you must provide\r
+complete object files to the recipients, so that they can relink them\r
+with the library after making changes to the library and recompiling\r
+it.  And you must show them these terms so they know their rights.\r
+\r
+  We protect your rights with a two-step method: (1) we copyright the\r
+library, and (2) we offer you this license, which gives you legal\r
+permission to copy, distribute and/or modify the library.\r
+\r
+  To protect each distributor, we want to make it very clear that\r
+there is no warranty for the free library.  Also, if the library is\r
+modified by someone else and passed on, the recipients should know\r
+that what they have is not the original version, so that the original\r
+author's reputation will not be affected by problems that might be\r
+introduced by others.\r
+\r
+  Finally, software patents pose a constant threat to the existence of\r
+any free program.  We wish to make sure that a company cannot\r
+effectively restrict the users of a free program by obtaining a\r
+restrictive license from a patent holder.  Therefore, we insist that\r
+any patent license obtained for a version of the library must be\r
+consistent with the full freedom of use specified in this license.\r
+\r
+  Most GNU software, including some libraries, is covered by the\r
+ordinary GNU General Public License.  This license, the GNU Lesser\r
+General Public License, applies to certain designated libraries, and\r
+is quite different from the ordinary General Public License.  We use\r
+this license for certain libraries in order to permit linking those\r
+libraries into non-free programs.\r
+\r
+  When a program is linked with a library, whether statically or using\r
+a shared library, the combination of the two is legally speaking a\r
+combined work, a derivative of the original library.  The ordinary\r
+General Public License therefore permits such linking only if the\r
+entire combination fits its criteria of freedom.  The Lesser General\r
+Public License permits more lax criteria for linking other code with\r
+the library.\r
+\r
+  We call this license the "Lesser" General Public License because it\r
+does Less to protect the user's freedom than the ordinary General\r
+Public License.  It also provides other free software developers Less\r
+of an advantage over competing non-free programs.  These disadvantages\r
+are the reason we use the ordinary General Public License for many\r
+libraries.  However, the Lesser license provides advantages in certain\r
+special circumstances.\r
+\r
+  For example, on rare occasions, there may be a special need to\r
+encourage the widest possible use of a certain library, so that it becomes\r
+a de-facto standard.  To achieve this, non-free programs must be\r
+allowed to use the library.  A more frequent case is that a free\r
+library does the same job as widely used non-free libraries.  In this\r
+case, there is little to gain by limiting the free library to free\r
+software only, so we use the Lesser General Public License.\r
+\r
+  In other cases, permission to use a particular library in non-free\r
+programs enables a greater number of people to use a large body of\r
+free software.  For example, permission to use the GNU C Library in\r
+non-free programs enables many more people to use the whole GNU\r
+operating system, as well as its variant, the GNU/Linux operating\r
+system.\r
+\r
+  Although the Lesser General Public License is Less protective of the\r
+users' freedom, it does ensure that the user of a program that is\r
+linked with the Library has the freedom and the wherewithal to run\r
+that program using a modified version of the Library.\r
+\r
+  The precise terms and conditions for copying, distribution and\r
+modification follow.  Pay close attention to the difference between a\r
+"work based on the library" and a "work that uses the library".  The\r
+former contains code derived from the library, whereas the latter must\r
+be combined with the library in order to run.\r
+\r
+                 GNU LESSER GENERAL PUBLIC LICENSE\r
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\r
+\r
+  0. This License Agreement applies to any software library or other\r
+program which contains a notice placed by the copyright holder or\r
+other authorized party saying it may be distributed under the terms of\r
+this Lesser General Public License (also called "this License").\r
+Each licensee is addressed as "you".\r
+\r
+  A "library" means a collection of software functions and/or data\r
+prepared so as to be conveniently linked with application programs\r
+(which use some of those functions and data) to form executables.\r
+\r
+  The "Library", below, refers to any such software library or work\r
+which has been distributed under these terms.  A "work based on the\r
+Library" means either the Library or any derivative work under\r
+copyright law: that is to say, a work containing the Library or a\r
+portion of it, either verbatim or with modifications and/or translated\r
+straightforwardly into another language.  (Hereinafter, translation is\r
+included without limitation in the term "modification".)\r
+\r
+  "Source code" for a work means the preferred form of the work for\r
+making modifications to it.  For a library, complete source code means\r
+all the source code for all modules it contains, plus any associated\r
+interface definition files, plus the scripts used to control compilation\r
+and installation of the library.\r
+\r
+  Activities other than copying, distribution and modification are not\r
+covered by this License; they are outside its scope.  The act of\r
+running a program using the Library is not restricted, and output from\r
+such a program is covered only if its contents constitute a work based\r
+on the Library (independent of the use of the Library in a tool for\r
+writing it).  Whether that is true depends on what the Library does\r
+and what the program that uses the Library does.\r
+\r
+  1. You may copy and distribute verbatim copies of the Library's\r
+complete source code as you receive it, in any medium, provided that\r
+you conspicuously and appropriately publish on each copy an\r
+appropriate copyright notice and disclaimer of warranty; keep intact\r
+all the notices that refer to this License and to the absence of any\r
+warranty; and distribute a copy of this License along with the\r
+Library.\r
+\r
+  You may charge a fee for the physical act of transferring a copy,\r
+and you may at your option offer warranty protection in exchange for a\r
+fee.\r
+\r
+  2. You may modify your copy or copies of the Library or any portion\r
+of it, thus forming a work based on the Library, and copy and\r
+distribute such modifications or work under the terms of Section 1\r
+above, provided that you also meet all of these conditions:\r
+\r
+    a) The modified work must itself be a software library.\r
+\r
+    b) You must cause the files modified to carry prominent notices\r
+    stating that you changed the files and the date of any change.\r
+\r
+    c) You must cause the whole of the work to be licensed at no\r
+    charge to all third parties under the terms of this License.\r
+\r
+    d) If a facility in the modified Library refers to a function or a\r
+    table of data to be supplied by an application program that uses\r
+    the facility, other than as an argument passed when the facility\r
+    is invoked, then you must make a good faith effort to ensure that,\r
+    in the event an application does not supply such function or\r
+    table, the facility still operates, and performs whatever part of\r
+    its purpose remains meaningful.\r
+\r
+    (For example, a function in a library to compute square roots has\r
+    a purpose that is entirely well-defined independent of the\r
+    application.  Therefore, Subsection 2d requires that any\r
+    application-supplied function or table used by this function must\r
+    be optional: if the application does not supply it, the square\r
+    root function must still compute square roots.)\r
+\r
+These requirements apply to the modified work as a whole.  If\r
+identifiable sections of that work are not derived from the Library,\r
+and can be reasonably considered independent and separate works in\r
+themselves, then this License, and its terms, do not apply to those\r
+sections when you distribute them as separate works.  But when you\r
+distribute the same sections as part of a whole which is a work based\r
+on the Library, the distribution of the whole must be on the terms of\r
+this License, whose permissions for other licensees extend to the\r
+entire whole, and thus to each and every part regardless of who wrote\r
+it.\r
+\r
+Thus, it is not the intent of this section to claim rights or contest\r
+your rights to work written entirely by you; rather, the intent is to\r
+exercise the right to control the distribution of derivative or\r
+collective works based on the Library.\r
+\r
+In addition, mere aggregation of another work not based on the Library\r
+with the Library (or with a work based on the Library) on a volume of\r
+a storage or distribution medium does not bring the other work under\r
+the scope of this License.\r
+\r
+  3. You may opt to apply the terms of the ordinary GNU General Public\r
+License instead of this License to a given copy of the Library.  To do\r
+this, you must alter all the notices that refer to this License, so\r
+that they refer to the ordinary GNU General Public License, version 2,\r
+instead of to this License.  (If a newer version than version 2 of the\r
+ordinary GNU General Public License has appeared, then you can specify\r
+that version instead if you wish.)  Do not make any other change in\r
+these notices.\r
+\r
+  Once this change is made in a given copy, it is irreversible for\r
+that copy, so the ordinary GNU General Public License applies to all\r
+subsequent copies and derivative works made from that copy.\r
+\r
+  This option is useful when you wish to copy part of the code of\r
+the Library into a program that is not a library.\r
+\r
+  4. You may copy and distribute the Library (or a portion or\r
+derivative of it, under Section 2) in object code or executable form\r
+under the terms of Sections 1 and 2 above provided that you accompany\r
+it with the complete corresponding machine-readable source code, which\r
+must be distributed under the terms of Sections 1 and 2 above on a\r
+medium customarily used for software interchange.\r
+\r
+  If distribution of object code is made by offering access to copy\r
+from a designated place, then offering equivalent access to copy the\r
+source code from the same place satisfies the requirement to\r
+distribute the source code, even though third parties are not\r
+compelled to copy the source along with the object code.\r
+\r
+  5. A program that contains no derivative of any portion of the\r
+Library, but is designed to work with the Library by being compiled or\r
+linked with it, is called a "work that uses the Library".  Such a\r
+work, in isolation, is not a derivative work of the Library, and\r
+therefore falls outside the scope of this License.\r
+\r
+  However, linking a "work that uses the Library" with the Library\r
+creates an executable that is a derivative of the Library (because it\r
+contains portions of the Library), rather than a "work that uses the\r
+library".  The executable is therefore covered by this License.\r
+Section 6 states terms for distribution of such executables.\r
+\r
+  When a "work that uses the Library" uses material from a header file\r
+that is part of the Library, the object code for the work may be a\r
+derivative work of the Library even though the source code is not.\r
+Whether this is true is especially significant if the work can be\r
+linked without the Library, or if the work is itself a library.  The\r
+threshold for this to be true is not precisely defined by law.\r
+\r
+  If such an object file uses only numerical parameters, data\r
+structure layouts and accessors, and small macros and small inline\r
+functions (ten lines or less in length), then the use of the object\r
+file is unrestricted, regardless of whether it is legally a derivative\r
+work.  (Executables containing this object code plus portions of the\r
+Library will still fall under Section 6.)\r
+\r
+  Otherwise, if the work is a derivative of the Library, you may\r
+distribute the object code for the work under the terms of Section 6.\r
+Any executables containing that work also fall under Section 6,\r
+whether or not they are linked directly with the Library itself.\r
+\r
+  6. As an exception to the Sections above, you may also combine or\r
+link a "work that uses the Library" with the Library to produce a\r
+work containing portions of the Library, and distribute that work\r
+under terms of your choice, provided that the terms permit\r
+modification of the work for the customer's own use and reverse\r
+engineering for debugging such modifications.\r
+\r
+  You must give prominent notice with each copy of the work that the\r
+Library is used in it and that the Library and its use are covered by\r
+this License.  You must supply a copy of this License.  If the work\r
+during execution displays copyright notices, you must include the\r
+copyright notice for the Library among them, as well as a reference\r
+directing the user to the copy of this License.  Also, you must do one\r
+of these things:\r
+\r
+    a) Accompany the work with the complete corresponding\r
+    machine-readable source code for the Library including whatever\r
+    changes were used in the work (which must be distributed under\r
+    Sections 1 and 2 above); and, if the work is an executable linked\r
+    with the Library, with the complete machine-readable "work that\r
+    uses the Library", as object code and/or source code, so that the\r
+    user can modify the Library and then relink to produce a modified\r
+    executable containing the modified Library.  (It is understood\r
+    that the user who changes the contents of definitions files in the\r
+    Library will not necessarily be able to recompile the application\r
+    to use the modified definitions.)\r
+\r
+    b) Use a suitable shared library mechanism for linking with the\r
+    Library.  A suitable mechanism is one that (1) uses at run time a\r
+    copy of the library already present on the user's computer system,\r
+    rather than copying library functions into the executable, and (2)\r
+    will operate properly with a modified version of the library, if\r
+    the user installs one, as long as the modified version is\r
+    interface-compatible with the version that the work was made with.\r
+\r
+    c) Accompany the work with a written offer, valid for at\r
+    least three years, to give the same user the materials\r
+    specified in Subsection 6a, above, for a charge no more\r
+    than the cost of performing this distribution.\r
+\r
+    d) If distribution of the work is made by offering access to copy\r
+    from a designated place, offer equivalent access to copy the above\r
+    specified materials from the same place.\r
+\r
+    e) Verify that the user has already received a copy of these\r
+    materials or that you have already sent this user a copy.\r
+\r
+  For an executable, the required form of the "work that uses the\r
+Library" must include any data and utility programs needed for\r
+reproducing the executable from it.  However, as a special exception,\r
+the materials to be distributed need not include anything that is\r
+normally distributed (in either source or binary form) with the major\r
+components (compiler, kernel, and so on) of the operating system on\r
+which the executable runs, unless that component itself accompanies\r
+the executable.\r
+\r
+  It may happen that this requirement contradicts the license\r
+restrictions of other proprietary libraries that do not normally\r
+accompany the operating system.  Such a contradiction means you cannot\r
+use both them and the Library together in an executable that you\r
+distribute.\r
+\r
+  7. You may place library facilities that are a work based on the\r
+Library side-by-side in a single library together with other library\r
+facilities not covered by this License, and distribute such a combined\r
+library, provided that the separate distribution of the work based on\r
+the Library and of the other library facilities is otherwise\r
+permitted, and provided that you do these two things:\r
+\r
+    a) Accompany the combined library with a copy of the same work\r
+    based on the Library, uncombined with any other library\r
+    facilities.  This must be distributed under the terms of the\r
+    Sections above.\r
+\r
+    b) Give prominent notice with the combined library of the fact\r
+    that part of it is a work based on the Library, and explaining\r
+    where to find the accompanying uncombined form of the same work.\r
+\r
+  8. You may not copy, modify, sublicense, link with, or distribute\r
+the Library except as expressly provided under this License.  Any\r
+attempt otherwise to copy, modify, sublicense, link with, or\r
+distribute the Library is void, and will automatically terminate your\r
+rights under this License.  However, parties who have received copies,\r
+or rights, from you under this License will not have their licenses\r
+terminated so long as such parties remain in full compliance.\r
+\r
+  9. You are not required to accept this License, since you have not\r
+signed it.  However, nothing else grants you permission to modify or\r
+distribute the Library or its derivative works.  These actions are\r
+prohibited by law if you do not accept this License.  Therefore, by\r
+modifying or distributing the Library (or any work based on the\r
+Library), you indicate your acceptance of this License to do so, and\r
+all its terms and conditions for copying, distributing or modifying\r
+the Library or works based on it.\r
+\r
+  10. Each time you redistribute the Library (or any work based on the\r
+Library), the recipient automatically receives a license from the\r
+original licensor to copy, distribute, link with or modify the Library\r
+subject to these terms and conditions.  You may not impose any further\r
+restrictions on the recipients' exercise of the rights granted herein.\r
+You are not responsible for enforcing compliance by third parties with\r
+this License.\r
+\r
+  11. If, as a consequence of a court judgment or allegation of patent\r
+infringement or for any other reason (not limited to patent issues),\r
+conditions are imposed on you (whether by court order, agreement or\r
+otherwise) that contradict the conditions of this License, they do not\r
+excuse you from the conditions of this License.  If you cannot\r
+distribute so as to satisfy simultaneously your obligations under this\r
+License and any other pertinent obligations, then as a consequence you\r
+may not distribute the Library at all.  For example, if a patent\r
+license would not permit royalty-free redistribution of the Library by\r
+all those who receive copies directly or indirectly through you, then\r
+the only way you could satisfy both it and this License would be to\r
+refrain entirely from distribution of the Library.\r
+\r
+If any portion of this section is held invalid or unenforceable under any\r
+particular circumstance, the balance of the section is intended to apply,\r
+and the section as a whole is intended to apply in other circumstances.\r
+\r
+It is not the purpose of this section to induce you to infringe any\r
+patents or other property right claims or to contest validity of any\r
+such claims; this section has the sole purpose of protecting the\r
+integrity of the free software distribution system which is\r
+implemented by public license practices.  Many people have made\r
+generous contributions to the wide range of software distributed\r
+through that system in reliance on consistent application of that\r
+system; it is up to the author/donor to decide if he or she is willing\r
+to distribute software through any other system and a licensee cannot\r
+impose that choice.\r
+\r
+This section is intended to make thoroughly clear what is believed to\r
+be a consequence of the rest of this License.\r
+\r
+  12. If the distribution and/or use of the Library is restricted in\r
+certain countries either by patents or by copyrighted interfaces, the\r
+original copyright holder who places the Library under this License may add\r
+an explicit geographical distribution limitation excluding those countries,\r
+so that distribution is permitted only in or among countries not thus\r
+excluded.  In such case, this License incorporates the limitation as if\r
+written in the body of this License.\r
+\r
+  13. The Free Software Foundation may publish revised and/or new\r
+versions of the Lesser General Public License from time to time.\r
+Such new versions will be similar in spirit to the present version,\r
+but may differ in detail to address new problems or concerns.\r
+\r
+Each version is given a distinguishing version number.  If the Library\r
+specifies a version number of this License which applies to it and\r
+"any later version", you have the option of following the terms and\r
+conditions either of that version or of any later version published by\r
+the Free Software Foundation.  If the Library does not specify a\r
+license version number, you may choose any version ever published by\r
+the Free Software Foundation.\r
+\r
+  14. If you wish to incorporate parts of the Library into other free\r
+programs whose distribution conditions are incompatible with these,\r
+write to the author to ask for permission.  For software which is\r
+copyrighted by the Free Software Foundation, write to the Free\r
+Software Foundation; we sometimes make exceptions for this.  Our\r
+decision will be guided by the two goals of preserving the free status\r
+of all derivatives of our free software and of promoting the sharing\r
+and reuse of software generally.\r
+\r
+                           NO WARRANTY\r
+\r
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO\r
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\r
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR\r
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY\r
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE\r
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE\r
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME\r
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\r
+\r
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\r
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY\r
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU\r
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR\r
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\r
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING\r
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A\r
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF\r
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
+DAMAGES.\r
+\r
+                    END OF TERMS AND CONDITIONS\r
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress.php b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/codepress.php
new file mode 100644 (file)
index 0000000..9a84865
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+require_once('../../initialise.php');
+if(!isset($_GET['id'])) die ('No file id specified');
+$f=kfmFile::getInstance($_GET['id']);
+if(!$f)die('File could not be loaded');
+switch($f->getExtension()){
+       case 'asp':
+               $lang='asp';
+               break;
+       case 'autoit':
+               $lang='autoit';
+               break;
+       case 'css':
+               $lang='css';
+               break;
+       case 'csharp':
+               $lang='csharp';
+               break;
+       case 'html':
+       case 'tpl':
+       case 'htm':
+               $lang='html';
+               break;
+       case 'java':
+       case 'j':
+               $lang='java';
+               break;
+       case 'js':
+               $lang='javascript';
+               break;
+       case 'perl':
+               $lang='perl';
+               break;
+       case 'php':
+       case 'php3':
+       case 'php4':
+               $lang='php';
+               break;
+       case 'ruby':
+       case 'rb':
+               $lang='ruby';
+               break;
+       case 'sql':
+               $lang='sql';
+               break;
+       case 'txt':
+               $lang='text';
+               break;
+       case 'vbscript':
+       case 'vba':
+               $lang='vbscript';
+               break;
+       case 'xsl':
+       case 'xml':
+               $lang='xsl';
+               break;
+       default:
+               $lang='generic';
+               break;
+}
+//print $kfm->doctype;
+?>
+<html>
+<head>
+<title>Codepress Editor</title>
+<script src="codepress-0.9.6/codepress.js" type="text/javascript"></script>
+<style type="text/css">
+textarea{
+       width:100%;
+       height:100%;
+       margin:0;
+}
+body{
+       background-color:#ddf;
+       margin:0;
+       padding:0;
+}
+</style>
+<script type="text/javascript">
+</script>
+</head>
+<body>
+<textarea id="editor_area" class="codepress <?php echo $lang;if(!$f->writable)echo ' readonly-on';?>"><?php echo $f->getContent();?></textarea>
+</body>
+</html>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/edit.png b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/edit.png
new file mode 100755 (executable)
index 0000000..cd77c30
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/edit.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/plugin.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/plugin.css
new file mode 100644 (file)
index 0000000..44bff66
--- /dev/null
@@ -0,0 +1,4 @@
+.kfm_plugin_codepress_contexticon{
+       background-image:url('edit.png');
+       background-repeat:no-repeat;
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/plugin.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/codepress/plugin.js
new file mode 100644 (file)
index 0000000..4b97305
--- /dev/null
@@ -0,0 +1,24 @@
+function plugin_codepress(){
+       this.name='codepress';
+       this.title=kfm.lang.EditTextFile;
+       this.mode=0; //only one file
+       this.defaultOpener=1;
+       this.writable=2;
+       this.category='edit';
+       this.extensions=['asp','autoit','css','csharp','html','tpl','htm','java','j','js','perl','php','ruby','sql','txt','vbscript','vba','xsl','xml'];
+       this.doFunction=function(files){
+               var F=File_getInstance(files[0]);
+               var url='plugins/codepress/codepress.php?id='+files[0]+'&random='+Math.random();
+               kfm_pluginIframeShow(url);
+               if(F.writable)kfm_pluginIframeButton('codepress_save('+files[0]+')','Save');
+       }
+}
+kfm_addHook(new plugin_codepress());
+
+function codepress_save(id){
+       var text;
+       var txtarea=document.getElementById('plugin_iframe_element').contentWindow.document.getElementById('editor_area');
+       if(txtarea)text=txtarea.value; // browser is not supported, if codepress works, the id is changed to editor_area_cp
+       else text=document.getElementById('plugin_iframe_element').contentWindow.editor_area.getCode();
+       x_kfm_saveTextFile(id,text,kfm_showMessage);
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/copy_to_clipboard/_clipboard.swf b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/copy_to_clipboard/_clipboard.swf
new file mode 100644 (file)
index 0000000..2cfe371
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/copy_to_clipboard/_clipboard.swf differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/copy_to_clipboard/plugin.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/copy_to_clipboard/plugin.js
new file mode 100644 (file)
index 0000000..ec4fa24
--- /dev/null
@@ -0,0 +1,36 @@
+function plugin_copy_to_clipboard(){
+       this.name='copy_to_clipboard';
+       this.title='copy to clipboard'; // TODO: String
+       this.mode=2;//single files
+       this.writable=2;//writable files
+       this.category='returning';
+       this.extensions='all';
+       this.doFunction=function(files){
+               kfm_copyToClipboard(files);
+       }
+}
+kfm_addHook(new plugin_copy_to_clipboard());
+
+function kfm_copyToClipboard(files){
+       x_kfm_getFileUrls(files,function(urls){
+               if(!urls.length)return;
+               copy_to_clipboard(urls.join("\n"));
+               new Notice("File URLs copied to browser clipboard"); // TODO: String
+       });
+}
+function copy_to_clipboard(text2copy) {
+       // function found here: http://webchicanery.com/2006/11/14/clipboard-copy-javascript/
+       if (window.clipboardData) {
+               window.clipboardData.setData("Text",text2copy);
+       } else {
+               var flashcopier = 'flashcopier';
+               if(!document.getElementById(flashcopier)) {
+                       var divholder = document.createElement('div');
+                       divholder.id = flashcopier;
+                       document.body.appendChild(divholder);
+               }
+               document.getElementById(flashcopier).innerHTML = '';
+               var divinfo = '<embed src="plugins/copy_to_clipboard/_clipboard.swf" FlashVars="clipboard='+escape(text2copy)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
+               document.getElementById(flashcopier).innerHTML = divinfo;
+       }
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/croparea.php b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/croparea.php
new file mode 100644 (file)
index 0000000..50b056c
--- /dev/null
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+<head>
+<script type="text/javascript" src="lib/prototype.js" language="javascript"></script>
+<script type="text/javascript" src="lib/scriptaculous.js?load=builder,dragdrop" language="javascript"></script>
+<script type="text/javascript" src="cropper.js" language="javascript"></script>
+<script type="text/javascript" language="javascript">
+var imageid=<?php print $_GET['id'];?>;
+var coordinates=null;
+var dimensions=null;
+Event.observe( window, 'load', function() {
+       new Cropper.Img(
+               'cropImage',
+               { onEndCrop: onEndCrop }
+       );
+} );
+function onEndCrop( coords, dims ) {
+       coordinates=coords;
+       dimensions=dims;
+}
+</script>
+<style type="text/css">
+img{
+       display:block;
+       margin:0;
+}
+body{
+       margin:0;
+       padding:0;
+}
+</style>
+</head>
+<body>
+<img src="<?php echo preg_replace('#plugins/cropper.*#','',$_SERVER['REQUEST_URI']); ?>get.php?id=<?php print $_GET['id'].'&'.rand(1,500);?>" alt="Crop image" id="cropImage" width="<?php print $_GET['width'];?>" height="<?php print $_GET['height'];?>" />
+</body>
+</html>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/cropper.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/cropper.css
new file mode 100644 (file)
index 0000000..c2e7598
--- /dev/null
@@ -0,0 +1,182 @@
+.imgCrop_wrap {\r
+       /* width: 500px;   @done_in_js */\r
+       /* height: 375px;  @done_in_js */\r
+       position: relative;\r
+       cursor: crosshair;\r
+}\r
+\r
+/* an extra classname is applied for Opera < 9.0 to fix it's lack of opacity support */\r
+.imgCrop_wrap.opera8 .imgCrop_overlay,\r
+.imgCrop_wrap.opera8 .imgCrop_clickArea { \r
+       background-color: transparent;\r
+}\r
+\r
+/* fix for IE displaying all boxes at line-height by default, although they are still 1 pixel high until we combine them with the pointless span */\r
+.imgCrop_wrap,\r
+.imgCrop_wrap * {\r
+       font-size: 0;\r
+}\r
+\r
+.imgCrop_overlay {\r
+       background-color: #000;\r
+       opacity: 0.5;\r
+       filter:alpha(opacity=50);\r
+       position: absolute;\r
+       width: 100%;\r
+       height: 100%;\r
+}\r
+\r
+.imgCrop_selArea {\r
+       position: absolute;\r
+       /* @done_in_js \r
+       top: 20px;\r
+       left: 20px;\r
+       width: 200px;\r
+       height: 200px;\r
+       background: transparent url(castle.jpg) no-repeat  -210px -110px;\r
+       */\r
+       cursor: move;\r
+       z-index: 2;\r
+}\r
+\r
+/* clickArea is all a fix for IE 5.5 & 6 to allow the user to click on the given area */\r
+.imgCrop_clickArea {\r
+       width: 100%;\r
+       height: 100%;\r
+       background-color: #FFF;\r
+       opacity: 0.01;\r
+       filter:alpha(opacity=01);\r
+}\r
+\r
+.imgCrop_marqueeHoriz {\r
+       position: absolute;\r
+       width: 100%;\r
+       height: 1px;\r
+       background: transparent url(marqueeHoriz.gif) repeat-x 0 0;\r
+       z-index: 3;\r
+}\r
+\r
+.imgCrop_marqueeVert {\r
+       position: absolute;\r
+       height: 100%;\r
+       width: 1px;\r
+       background: transparent url(marqueeVert.gif) repeat-y 0 0;\r
+       z-index: 3;\r
+}\r
+\r
+/* \r
+ *  FIX MARCHING ANTS IN IE\r
+ *     As IE <6 tries to load background images we can uncomment the follwoing hack \r
+ *  to remove that issue, not as pretty - but is anything in IE?\r
+ *  And yes I do know that 'filter' is evil, but it will make it look semi decent in IE\r
+ *\r
+* html .imgCrop_marqueeHoriz,\r
+* html .imgCrop_marqueeVert {\r
+       background: transparent;\r
+       filter: Invert; \r
+}\r
+* html .imgCrop_marqueeNorth { border-top: 1px dashed #000; }\r
+* html .imgCrop_marqueeEast  { border-right: 1px dashed #000; }\r
+* html .imgCrop_marqueeSouth { border-bottom: 1px dashed #000; }\r
+* html .imgCrop_marqueeWest  { border-left: 1px dashed #000; }\r
+*/\r
+\r
+.imgCrop_marqueeNorth { top: 0; left: 0; }\r
+.imgCrop_marqueeEast  { top: 0; right: 0; }\r
+.imgCrop_marqueeSouth { bottom: 0px; left: 0; }\r
+.imgCrop_marqueeWest  { top: 0; left: 0; }\r
+\r
+\r
+.imgCrop_handle {\r
+       position: absolute;\r
+       border: 1px solid #333;\r
+       width: 6px;\r
+       height: 6px;\r
+       background: #FFF;\r
+       opacity: 0.5;\r
+       filter:alpha(opacity=50);\r
+       z-index: 4;\r
+}\r
+\r
+/* fix IE 5 box model */\r
+* html .imgCrop_handle {\r
+       width: 8px;\r
+       height: 8px;\r
+       wid\th: 6px;\r
+       hei\ght: 6px;\r
+}\r
+\r
+.imgCrop_handleN {\r
+       top: -3px;\r
+       left: 0;\r
+       /* margin-left: 49%;    @done_in_js */\r
+       cursor: n-resize;\r
+}\r
+\r
+.imgCrop_handleNE { \r
+       top: -3px;\r
+       right: -3px;\r
+       cursor: ne-resize;\r
+}\r
+\r
+.imgCrop_handleE {\r
+       top: 0;\r
+       right: -3px;\r
+       /* margin-top: 49%;    @done_in_js */\r
+       cursor: e-resize;\r
+}\r
+\r
+.imgCrop_handleSE {\r
+       right: -3px;\r
+       bottom: -3px;\r
+       cursor: se-resize;\r
+}\r
+\r
+.imgCrop_handleS {\r
+       right: 0;\r
+       bottom: -3px;\r
+       /* margin-right: 49%; @done_in_js */\r
+       cursor: s-resize;\r
+}\r
+\r
+.imgCrop_handleSW {\r
+       left: -3px;\r
+       bottom: -3px;\r
+       cursor: sw-resize;\r
+}\r
+\r
+.imgCrop_handleW {\r
+       top: 0;\r
+       left: -3px;\r
+       /* margin-top: 49%;  @done_in_js */\r
+       cursor: w-resize;\r
+}\r
+\r
+.imgCrop_handleNW {\r
+       top: -3px;\r
+       left: -3px;\r
+       cursor: nw-resize;\r
+}\r
+\r
+/**\r
+ * Create an area to click & drag around on as the default browser behaviour is to let you drag the image \r
+ */\r
+.imgCrop_dragArea {\r
+       width: 100%;\r
+       height: 100%;\r
+       z-index: 200;\r
+       position: absolute;\r
+       top: 0;\r
+       left: 0;\r
+}\r
+\r
+.imgCrop_previewWrap {\r
+       /* width: 200px;  @done_in_js */\r
+       /* height: 200px; @done_in_js */\r
+       overflow: hidden;\r
+       position: relative;\r
+}\r
+\r
+.imgCrop_previewWrap img {\r
+       position: absolute;\r
+}
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/cropper.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/cropper.js
new file mode 100644 (file)
index 0000000..c2ecc99
--- /dev/null
@@ -0,0 +1,566 @@
+/** 
+ * Copyright (c) 2006, David Spurr (http://www.defusion.org.uk/)
+ * 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 David Spurr 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.
+ * 
+ * http://www.opensource.org/licenses/bsd-license.php
+ * 
+ * See scriptaculous.js for full scriptaculous licence
+ */
+
+var CropDraggable=Class.create();
+Object.extend(Object.extend(CropDraggable.prototype,Draggable.prototype),{initialize:function(_1){
+this.options=Object.extend({drawMethod:function(){
+}},arguments[1]||{});
+this.element=$(_1);
+this.handle=this.element;
+this.delta=this.currentDelta();
+this.dragging=false;
+this.eventMouseDown=this.initDrag.bindAsEventListener(this);
+Event.observe(this.handle,"mousedown",this.eventMouseDown);
+Draggables.register(this);
+},draw:function(_2){
+var _3=Position.cumulativeOffset(this.element);
+var d=this.currentDelta();
+_3[0]-=d[0];
+_3[1]-=d[1];
+var p=[0,1].map(function(i){
+return (_2[i]-_3[i]-this.offset[i]);
+}.bind(this));
+this.options.drawMethod(p);
+}});
+var Cropper={};
+Cropper.Img=Class.create();
+Cropper.Img.prototype={initialize:function(_7,_8){
+this.options=Object.extend({ratioDim:{x:0,y:0},minWidth:0,minHeight:0,displayOnInit:false,onEndCrop:Prototype.emptyFunction,captureKeys:true,onloadCoords:null,maxWidth:0,maxHeight:0},_8||{});
+this.img=$(_7);
+this.clickCoords={x:0,y:0};
+this.dragging=false;
+this.resizing=false;
+this.isWebKit=/Konqueror|Safari|KHTML/.test(navigator.userAgent);
+this.isIE=/MSIE/.test(navigator.userAgent);
+this.isOpera8=/Opera\s[1-8]/.test(navigator.userAgent);
+this.ratioX=0;
+this.ratioY=0;
+this.attached=false;
+this.fixedWidth=(this.options.maxWidth>0&&(this.options.minWidth>=this.options.maxWidth));
+this.fixedHeight=(this.options.maxHeight>0&&(this.options.minHeight>=this.options.maxHeight));
+if(typeof this.img=="undefined"){
+return;
+}
+$A(document.getElementsByTagName("script")).each(function(s){
+if(s.src.match(/cropper\.js/)){
+var _a=s.src.replace(/cropper\.js(.*)?/,"");
+var _b=document.createElement("link");
+_b.rel="stylesheet";
+_b.type="text/css";
+_b.href=_a+"cropper.css";
+_b.media="screen";
+document.getElementsByTagName("head")[0].appendChild(_b);
+}
+});
+if(this.options.ratioDim.x>0&&this.options.ratioDim.y>0){
+var _c=this.getGCD(this.options.ratioDim.x,this.options.ratioDim.y);
+this.ratioX=this.options.ratioDim.x/_c;
+this.ratioY=this.options.ratioDim.y/_c;
+}
+this.subInitialize();
+if(this.img.complete||this.isWebKit){
+this.onLoad();
+}else{
+Event.observe(this.img,"load",this.onLoad.bindAsEventListener(this));
+}
+},getGCD:function(a,b){
+if(b==0){
+return a;
+}
+return this.getGCD(b,a%b);
+},onLoad:function(){
+var _f="imgCrop_";
+var _10=this.img.parentNode;
+var _11="";
+if(this.isOpera8){
+_11=" opera8";
+}
+this.imgWrap=Builder.node("div",{"class":_f+"wrap"+_11});
+this.north=Builder.node("div",{"class":_f+"overlay "+_f+"north"},[Builder.node("span")]);
+this.east=Builder.node("div",{"class":_f+"overlay "+_f+"east"},[Builder.node("span")]);
+this.south=Builder.node("div",{"class":_f+"overlay "+_f+"south"},[Builder.node("span")]);
+this.west=Builder.node("div",{"class":_f+"overlay "+_f+"west"},[Builder.node("span")]);
+var _12=[this.north,this.east,this.south,this.west];
+this.dragArea=Builder.node("div",{"class":_f+"dragArea"},_12);
+this.handleN=Builder.node("div",{"class":_f+"handle "+_f+"handleN"});
+this.handleNE=Builder.node("div",{"class":_f+"handle "+_f+"handleNE"});
+this.handleE=Builder.node("div",{"class":_f+"handle "+_f+"handleE"});
+this.handleSE=Builder.node("div",{"class":_f+"handle "+_f+"handleSE"});
+this.handleS=Builder.node("div",{"class":_f+"handle "+_f+"handleS"});
+this.handleSW=Builder.node("div",{"class":_f+"handle "+_f+"handleSW"});
+this.handleW=Builder.node("div",{"class":_f+"handle "+_f+"handleW"});
+this.handleNW=Builder.node("div",{"class":_f+"handle "+_f+"handleNW"});
+this.selArea=Builder.node("div",{"class":_f+"selArea"},[Builder.node("div",{"class":_f+"marqueeHoriz "+_f+"marqueeNorth"},[Builder.node("span")]),Builder.node("div",{"class":_f+"marqueeVert "+_f+"marqueeEast"},[Builder.node("span")]),Builder.node("div",{"class":_f+"marqueeHoriz "+_f+"marqueeSouth"},[Builder.node("span")]),Builder.node("div",{"class":_f+"marqueeVert "+_f+"marqueeWest"},[Builder.node("span")]),this.handleN,this.handleNE,this.handleE,this.handleSE,this.handleS,this.handleSW,this.handleW,this.handleNW,Builder.node("div",{"class":_f+"clickArea"})]);
+this.imgWrap.appendChild(this.img);
+this.imgWrap.appendChild(this.dragArea);
+this.dragArea.appendChild(this.selArea);
+this.dragArea.appendChild(Builder.node("div",{"class":_f+"clickArea"}));
+_10.appendChild(this.imgWrap);
+this.startDragBind=this.startDrag.bindAsEventListener(this);
+Event.observe(this.dragArea,"mousedown",this.startDragBind);
+this.onDragBind=this.onDrag.bindAsEventListener(this);
+Event.observe(document,"mousemove",this.onDragBind);
+this.endCropBind=this.endCrop.bindAsEventListener(this);
+Event.observe(document,"mouseup",this.endCropBind);
+this.resizeBind=this.startResize.bindAsEventListener(this);
+this.handles=[this.handleN,this.handleNE,this.handleE,this.handleSE,this.handleS,this.handleSW,this.handleW,this.handleNW];
+this.registerHandles(true);
+if(this.options.captureKeys){
+this.keysBind=this.handleKeys.bindAsEventListener(this);
+Event.observe(document,"keypress",this.keysBind);
+}
+new CropDraggable(this.selArea,{drawMethod:this.moveArea.bindAsEventListener(this)});
+this.setParams();
+},registerHandles:function(_13){
+for(var i=0;i<this.handles.length;i++){
+var _15=$(this.handles[i]);
+if(_13){
+var _16=false;
+if(this.fixedWidth&&this.fixedHeight){
+_16=true;
+}else{
+if(this.fixedWidth||this.fixedHeight){
+var _17=_15.className.match(/([S|N][E|W])$/);
+var _18=_15.className.match(/(E|W)$/);
+var _19=_15.className.match(/(N|S)$/);
+if(_17){
+_16=true;
+}else{
+if(this.fixedWidth&&_18){
+_16=true;
+}else{
+if(this.fixedHeight&&_19){
+_16=true;
+}
+}
+}
+}
+}
+if(_16){
+_15.hide();
+}else{
+Event.observe(_15,"mousedown",this.resizeBind);
+}
+}else{
+_15.show();
+Event.stopObserving(_15,"mousedown",this.resizeBind);
+}
+}
+},setParams:function(){
+this.imgW=this.img.width;
+this.imgH=this.img.height;
+$(this.north).setStyle({height:0});
+$(this.east).setStyle({width:0,height:0});
+$(this.south).setStyle({height:0});
+$(this.west).setStyle({width:0,height:0});
+$(this.imgWrap).setStyle({"width":this.imgW+"px","height":this.imgH+"px"});
+$(this.selArea).hide();
+var _1a={x1:0,y1:0,x2:0,y2:0};
+var _1b=false;
+if(this.options.onloadCoords!=null){
+_1a=this.cloneCoords(this.options.onloadCoords);
+_1b=true;
+}else{
+if(this.options.ratioDim.x>0&&this.options.ratioDim.y>0){
+_1a.x1=Math.ceil((this.imgW-this.options.ratioDim.x)/2);
+_1a.y1=Math.ceil((this.imgH-this.options.ratioDim.y)/2);
+_1a.x2=_1a.x1+this.options.ratioDim.x;
+_1a.y2=_1a.y1+this.options.ratioDim.y;
+_1b=true;
+}
+}
+this.setAreaCoords(_1a,false,false,1);
+if(this.options.displayOnInit&&_1b){
+this.selArea.show();
+this.drawArea();
+this.endCrop();
+}
+this.attached=true;
+},remove:function(){
+if(this.attached){
+this.attached=false;
+this.imgWrap.parentNode.insertBefore(this.img,this.imgWrap);
+this.imgWrap.parentNode.removeChild(this.imgWrap);
+Event.stopObserving(this.dragArea,"mousedown",this.startDragBind);
+Event.stopObserving(document,"mousemove",this.onDragBind);
+Event.stopObserving(document,"mouseup",this.endCropBind);
+this.registerHandles(false);
+if(this.options.captureKeys){
+Event.stopObserving(document,"keypress",this.keysBind);
+}
+}
+},reset:function(){
+if(!this.attached){
+this.onLoad();
+}else{
+this.setParams();
+}
+this.endCrop();
+},handleKeys:function(e){
+var dir={x:0,y:0};
+if(!this.dragging){
+switch(e.keyCode){
+case (37):
+dir.x=-1;
+break;
+case (38):
+dir.y=-1;
+break;
+case (39):
+dir.x=1;
+break;
+case (40):
+dir.y=1;
+break;
+}
+if(dir.x!=0||dir.y!=0){
+if(e.shiftKey){
+dir.x*=10;
+dir.y*=10;
+}
+this.moveArea([this.areaCoords.x1+dir.x,this.areaCoords.y1+dir.y]);
+Event.stop(e);
+}
+}
+},calcW:function(){
+return (this.areaCoords.x2-this.areaCoords.x1);
+},calcH:function(){
+return (this.areaCoords.y2-this.areaCoords.y1);
+},moveArea:function(_1e){
+this.setAreaCoords({x1:_1e[0],y1:_1e[1],x2:_1e[0]+this.calcW(),y2:_1e[1]+this.calcH()},true,false);
+this.drawArea();
+},cloneCoords:function(_1f){
+return {x1:_1f.x1,y1:_1f.y1,x2:_1f.x2,y2:_1f.y2};
+},setAreaCoords:function(_20,_21,_22,_23,_24){
+if(_21){
+var _25=_20.x2-_20.x1;
+var _26=_20.y2-_20.y1;
+if(_20.x1<0){
+_20.x1=0;
+_20.x2=_25;
+}
+if(_20.y1<0){
+_20.y1=0;
+_20.y2=_26;
+}
+if(_20.x2>this.imgW){
+_20.x2=this.imgW;
+_20.x1=this.imgW-_25;
+}
+if(_20.y2>this.imgH){
+_20.y2=this.imgH;
+_20.y1=this.imgH-_26;
+}
+}else{
+if(_20.x1<0){
+_20.x1=0;
+}
+if(_20.y1<0){
+_20.y1=0;
+}
+if(_20.x2>this.imgW){
+_20.x2=this.imgW;
+}
+if(_20.y2>this.imgH){
+_20.y2=this.imgH;
+}
+if(_23!=null){
+if(this.ratioX>0){
+this.applyRatio(_20,{x:this.ratioX,y:this.ratioY},_23,_24);
+}else{
+if(_22){
+this.applyRatio(_20,{x:1,y:1},_23,_24);
+}
+}
+var _27=[this.options.minWidth,this.options.minHeight];
+var _28=[this.options.maxWidth,this.options.maxHeight];
+if(_27[0]>0||_27[1]>0||_28[0]>0||_28[1]>0){
+var _29={a1:_20.x1,a2:_20.x2};
+var _2a={a1:_20.y1,a2:_20.y2};
+var _2b={min:0,max:this.imgW};
+var _2c={min:0,max:this.imgH};
+if((_27[0]!=0||_27[1]!=0)&&_22){
+if(_27[0]>0){
+_27[1]=_27[0];
+}else{
+if(_27[1]>0){
+_27[0]=_27[1];
+}
+}
+}
+if((_28[0]!=0||_28[0]!=0)&&_22){
+if(_28[0]>0&&_28[0]<=_28[1]){
+_28[1]=_28[0];
+}else{
+if(_28[1]>0&&_28[1]<=_28[0]){
+_28[0]=_28[1];
+}
+}
+}
+if(_27[0]>0){
+this.applyDimRestriction(_29,_27[0],_23.x,_2b,"min");
+}
+if(_27[1]>1){
+this.applyDimRestriction(_2a,_27[1],_23.y,_2c,"min");
+}
+if(_28[0]>0){
+this.applyDimRestriction(_29,_28[0],_23.x,_2b,"max");
+}
+if(_28[1]>1){
+this.applyDimRestriction(_2a,_28[1],_23.y,_2c,"max");
+}
+_20={x1:_29.a1,y1:_2a.a1,x2:_29.a2,y2:_2a.a2};
+}
+}
+}
+this.areaCoords=_20;
+},applyDimRestriction:function(_2d,val,_2f,_30,_31){
+var _32;
+if(_31=="min"){
+_32=((_2d.a2-_2d.a1)<val);
+}else{
+_32=((_2d.a2-_2d.a1)>val);
+}
+if(_32){
+if(_2f==1){
+_2d.a2=_2d.a1+val;
+}else{
+_2d.a1=_2d.a2-val;
+}
+if(_2d.a1<_30.min){
+_2d.a1=_30.min;
+_2d.a2=val;
+}else{
+if(_2d.a2>_30.max){
+_2d.a1=_30.max-val;
+_2d.a2=_30.max;
+}
+}
+}
+},applyRatio:function(_33,_34,_35,_36){
+var _37;
+if(_36=="N"||_36=="S"){
+_37=this.applyRatioToAxis({a1:_33.y1,b1:_33.x1,a2:_33.y2,b2:_33.x2},{a:_34.y,b:_34.x},{a:_35.y,b:_35.x},{min:0,max:this.imgW});
+_33.x1=_37.b1;
+_33.y1=_37.a1;
+_33.x2=_37.b2;
+_33.y2=_37.a2;
+}else{
+_37=this.applyRatioToAxis({a1:_33.x1,b1:_33.y1,a2:_33.x2,b2:_33.y2},{a:_34.x,b:_34.y},{a:_35.x,b:_35.y},{min:0,max:this.imgH});
+_33.x1=_37.a1;
+_33.y1=_37.b1;
+_33.x2=_37.a2;
+_33.y2=_37.b2;
+}
+},applyRatioToAxis:function(_38,_39,_3a,_3b){
+var _3c=Object.extend(_38,{});
+var _3d=_3c.a2-_3c.a1;
+var _3e=Math.floor(_3d*_39.b/_39.a);
+var _3f;
+var _40;
+var _41=null;
+if(_3a.b==1){
+_3f=_3c.b1+_3e;
+if(_3f>_3b.max){
+_3f=_3b.max;
+_41=_3f-_3c.b1;
+}
+_3c.b2=_3f;
+}else{
+_3f=_3c.b2-_3e;
+if(_3f<_3b.min){
+_3f=_3b.min;
+_41=_3f+_3c.b2;
+}
+_3c.b1=_3f;
+}
+if(_41!=null){
+_40=Math.floor(_41*_39.a/_39.b);
+if(_3a.a==1){
+_3c.a2=_3c.a1+_40;
+}else{
+_3c.a1=_3c.a1=_3c.a2-_40;
+}
+}
+return _3c;
+},drawArea:function(){
+var _42=this.calcW();
+var _43=this.calcH();
+var px="px";
+var _45=[this.areaCoords.x1+px,this.areaCoords.y1+px,_42+px,_43+px,this.areaCoords.x2+px,this.areaCoords.y2+px,(this.img.width-this.areaCoords.x2)+px,(this.img.height-this.areaCoords.y2)+px];
+var _46=this.selArea.style;
+_46.left=_45[0];
+_46.top=_45[1];
+_46.width=_45[2];
+_46.height=_45[3];
+var _47=Math.ceil((_42-6)/2)+px;
+var _48=Math.ceil((_43-6)/2)+px;
+this.handleN.style.left=_47;
+this.handleE.style.top=_48;
+this.handleS.style.left=_47;
+this.handleW.style.top=_48;
+this.north.style.height=_45[1];
+var _49=this.east.style;
+_49.top=_45[1];
+_49.height=_45[3];
+_49.left=_45[4];
+_49.width=_45[6];
+var _4a=this.south.style;
+_4a.top=_45[5];
+_4a.height=_45[7];
+var _4b=this.west.style;
+_4b.top=_45[1];
+_4b.height=_45[3];
+_4b.width=_45[0];
+this.subDrawArea();
+this.forceReRender();
+},forceReRender:function(){
+if(this.isIE||this.isWebKit){
+var n=document.createTextNode(" ");
+var d,el,fixEL,i;
+if(this.isIE){
+fixEl=this.selArea;
+}else{
+if(this.isWebKit){
+fixEl=document.getElementsByClassName("imgCrop_marqueeSouth",this.imgWrap)[0];
+d=Builder.node("div","");
+d.style.visibility="hidden";
+var _4e=["SE","S","SW"];
+for(i=0;i<_4e.length;i++){
+el=document.getElementsByClassName("imgCrop_handle"+_4e[i],this.selArea)[0];
+if(el.childNodes.length){
+el.removeChild(el.childNodes[0]);
+}
+el.appendChild(d);
+}
+}
+}
+fixEl.appendChild(n);
+fixEl.removeChild(n);
+}
+},startResize:function(e){
+this.startCoords=this.cloneCoords(this.areaCoords);
+this.resizing=true;
+this.resizeHandle=Event.element(e).classNames().toString().replace(/([^N|NE|E|SE|S|SW|W|NW])+/,"");
+Event.stop(e);
+},startDrag:function(e){
+this.selArea.show();
+this.clickCoords=this.getCurPos(e);
+this.setAreaCoords({x1:this.clickCoords.x,y1:this.clickCoords.y,x2:this.clickCoords.x,y2:this.clickCoords.y},false,false,null);
+this.dragging=true;
+this.onDrag(e);
+Event.stop(e);
+},getCurPos:function(e){
+var el=this.imgWrap,wrapOffsets=Position.cumulativeOffset(el);
+while(el.nodeName!="BODY"){
+wrapOffsets[1]-=el.scrollTop||0;
+wrapOffsets[0]-=el.scrollLeft||0;
+el=el.parentNode;
+}
+return curPos={x:Event.pointerX(e)-wrapOffsets[0],y:Event.pointerY(e)-wrapOffsets[1]};
+},onDrag:function(e){
+if(this.dragging||this.resizing){
+var _54=null;
+var _55=this.getCurPos(e);
+var _56=this.cloneCoords(this.areaCoords);
+var _57={x:1,y:1};
+if(this.dragging){
+if(_55.x<this.clickCoords.x){
+_57.x=-1;
+}
+if(_55.y<this.clickCoords.y){
+_57.y=-1;
+}
+this.transformCoords(_55.x,this.clickCoords.x,_56,"x");
+this.transformCoords(_55.y,this.clickCoords.y,_56,"y");
+}else{
+if(this.resizing){
+_54=this.resizeHandle;
+if(_54.match(/E/)){
+this.transformCoords(_55.x,this.startCoords.x1,_56,"x");
+if(_55.x<this.startCoords.x1){
+_57.x=-1;
+}
+}else{
+if(_54.match(/W/)){
+this.transformCoords(_55.x,this.startCoords.x2,_56,"x");
+if(_55.x<this.startCoords.x2){
+_57.x=-1;
+}
+}
+}
+if(_54.match(/N/)){
+this.transformCoords(_55.y,this.startCoords.y2,_56,"y");
+if(_55.y<this.startCoords.y2){
+_57.y=-1;
+}
+}else{
+if(_54.match(/S/)){
+this.transformCoords(_55.y,this.startCoords.y1,_56,"y");
+if(_55.y<this.startCoords.y1){
+_57.y=-1;
+}
+}
+}
+}
+}
+this.setAreaCoords(_56,false,e.shiftKey,_57,_54);
+this.drawArea();
+Event.stop(e);
+}
+},transformCoords:function(_58,_59,_5a,_5b){
+var _5c=[_58,_59];
+if(_58>_59){
+_5c.reverse();
+}
+_5a[_5b+"1"]=_5c[0];
+_5a[_5b+"2"]=_5c[1];
+},endCrop:function(){
+this.dragging=false;
+this.resizing=false;
+this.options.onEndCrop(this.areaCoords,{width:this.calcW(),height:this.calcH()});
+},subInitialize:function(){
+},subDrawArea:function(){
+}};
+Cropper.ImgWithPreview=Class.create();
+Object.extend(Object.extend(Cropper.ImgWithPreview.prototype,Cropper.Img.prototype),{subInitialize:function(){
+this.hasPreviewImg=false;
+if(typeof (this.options.previewWrap)!="undefined"&&this.options.minWidth>0&&this.options.minHeight>0){
+this.previewWrap=$(this.options.previewWrap);
+this.previewImg=this.img.cloneNode(false);
+this.previewImg.id="imgCrop_"+this.previewImg.id;
+this.options.displayOnInit=true;
+this.hasPreviewImg=true;
+this.previewWrap.addClassName("imgCrop_previewWrap");
+this.previewWrap.setStyle({width:this.options.minWidth+"px",height:this.options.minHeight+"px"});
+this.previewWrap.appendChild(this.previewImg);
+}
+},subDrawArea:function(){
+if(this.hasPreviewImg){
+var _5d=this.calcW();
+var _5e=this.calcH();
+var _5f={x:this.imgW/_5d,y:this.imgH/_5e};
+var _60={x:_5d/this.options.minWidth,y:_5e/this.options.minHeight};
+var _61={w:Math.ceil(this.options.minWidth*_5f.x)+"px",h:Math.ceil(this.options.minHeight*_5f.y)+"px",x:"-"+Math.ceil(this.areaCoords.x1/_60.x)+"px",y:"-"+Math.ceil(this.areaCoords.y1/_60.y)+"px"};
+var _62=this.previewImg.style;
+_62.width=_61.w;
+_62.height=_61.h;
+_62.left=_61.x;
+_62.top=_61.y;
+}
+}});
+
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/img/crop.gif b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/img/crop.gif
new file mode 100644 (file)
index 0000000..da72d70
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/img/crop.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/builder.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/builder.js
new file mode 100644 (file)
index 0000000..5b15ba9
--- /dev/null
@@ -0,0 +1,101 @@
+// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// See scriptaculous.js for full license.
+
+var Builder = {
+  NODEMAP: {
+    AREA: 'map',
+    CAPTION: 'table',
+    COL: 'table',
+    COLGROUP: 'table',
+    LEGEND: 'fieldset',
+    OPTGROUP: 'select',
+    OPTION: 'select',
+    PARAM: 'object',
+    TBODY: 'table',
+    TD: 'table',
+    TFOOT: 'table',
+    TH: 'table',
+    THEAD: 'table',
+    TR: 'table'
+  },
+  // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+  //       due to a Firefox bug
+  node: function(elementName) {
+    elementName = elementName.toUpperCase();
+    
+    // try innerHTML approach
+    var parentTag = this.NODEMAP[elementName] || 'div';
+    var parentElement = document.createElement(parentTag);
+    try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+      parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+    } catch(e) {}
+    var element = parentElement.firstChild || null;
+      
+    // see if browser added wrapping tags
+    if(element && (element.tagName != elementName))
+      element = element.getElementsByTagName(elementName)[0];
+    
+    // fallback to createElement approach
+    if(!element) element = document.createElement(elementName);
+    
+    // abort if nothing could be created
+    if(!element) return;
+
+    // attributes (or text)
+    if(arguments[1])
+      if(this._isStringOrNumber(arguments[1]) ||
+        (arguments[1] instanceof Array)) {
+          this._children(element, arguments[1]);
+        } else {
+          var attrs = this._attributes(arguments[1]);
+          if(attrs.length) {
+            try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+              parentElement.innerHTML = "<" +elementName + " " +
+                attrs + "></" + elementName + ">";
+            } catch(e) {}
+            element = parentElement.firstChild || null;
+            // workaround firefox 1.0.X bug
+            if(!element) {
+              element = document.createElement(elementName);
+              for(attr in arguments[1]) 
+                element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+            }
+            if(element.tagName != elementName)
+              element = parentElement.getElementsByTagName(elementName)[0];
+            }
+        } 
+
+    // text, or array of children
+    if(arguments[2])
+      this._children(element, arguments[2]);
+
+     return element;
+  },
+  _text: function(text) {
+     return document.createTextNode(text);
+  },
+  _attributes: function(attributes) {
+    var attrs = [];
+    for(attribute in attributes)
+      attrs.push((attribute=='className' ? 'class' : attribute) +
+          '="' + attributes[attribute].toString().escapeHTML() + '"');
+    return attrs.join(" ");
+  },
+  _children: function(element, children) {
+    if(typeof children=='object') { // array can hold nodes and text
+      children.flatten().each( function(e) {
+        if(typeof e=='object')
+          element.appendChild(e)
+        else
+          if(Builder._isStringOrNumber(e))
+            element.appendChild(Builder._text(e));
+      });
+    } else
+      if(Builder._isStringOrNumber(children)) 
+         element.appendChild(Builder._text(children));
+  },
+  _isStringOrNumber: function(param) {
+    return(typeof param=='string' || typeof param=='number');
+  }
+}
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/controls.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/controls.js
new file mode 100644 (file)
index 0000000..de0261e
--- /dev/null
@@ -0,0 +1,815 @@
+// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//           (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+//           (c) 2005 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+//  Richard Livsey
+//  Rahul Bhargava
+//  Rob Wills
+// 
+// See scriptaculous.js for full license.
+
+// Autocompleter.Base handles all the autocompletion functionality 
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least, 
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method 
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most 
+// useful when one of the tokens is \n (a newline), as it 
+// allows smart autocompletion after linebreaks.
+
+var Autocompleter = {}
+Autocompleter.Base = function() {};
+Autocompleter.Base.prototype = {
+  baseInitialize: function(element, update, options) {
+    this.element     = $(element); 
+    this.update      = $(update);  
+    this.hasFocus    = false; 
+    this.changed     = false; 
+    this.active      = false; 
+    this.index       = 0;     
+    this.entryCount  = 0;
+
+    if (this.setOptions)
+      this.setOptions(options);
+    else
+      this.options = options || {};
+
+    this.options.paramName    = this.options.paramName || this.element.name;
+    this.options.tokens       = this.options.tokens || [];
+    this.options.frequency    = this.options.frequency || 0.4;
+    this.options.minChars     = this.options.minChars || 1;
+    this.options.onShow       = this.options.onShow || 
+    function(element, update){ 
+      if(!update.style.position || update.style.position=='absolute') {
+        update.style.position = 'absolute';
+        Position.clone(element, update, {setHeight: false, offsetTop: element.offsetHeight});
+      }
+      Effect.Appear(update,{duration:0.15});
+    };
+    this.options.onHide = this.options.onHide || 
+    function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+    if (typeof(this.options.tokens) == 'string') 
+      this.options.tokens = new Array(this.options.tokens);
+
+    this.observer = null;
+    
+    this.element.setAttribute('autocomplete','off');
+
+    Element.hide(this.update);
+
+    Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
+    Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));
+  },
+
+  show: function() {
+    if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+    if(!this.iefix && 
+      (navigator.appVersion.indexOf('MSIE')>0) &&
+      (navigator.userAgent.indexOf('Opera')<0) &&
+      (Element.getStyle(this.update, 'position')=='absolute')) {
+      new Insertion.After(this.update, 
+       '<iframe id="' + this.update.id + '_iefix" '+
+       'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+       'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+      this.iefix = $(this.update.id+'_iefix');
+    }
+    if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+  },
+  
+  fixIEOverlapping: function() {
+    Position.clone(this.update, this.iefix);
+    this.iefix.style.zIndex = 1;
+    this.update.style.zIndex = 2;
+    Element.show(this.iefix);
+  },
+
+  hide: function() {
+    this.stopIndicator();
+    if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+    if(this.iefix) Element.hide(this.iefix);
+  },
+
+  startIndicator: function() {
+    if(this.options.indicator) Element.show(this.options.indicator);
+  },
+
+  stopIndicator: function() {
+    if(this.options.indicator) Element.hide(this.options.indicator);
+  },
+
+  onKeyPress: function(event) {
+    if(this.active)
+      switch(event.keyCode) {
+       case Event.KEY_TAB:
+       case Event.KEY_RETURN:
+         this.selectEntry();
+         Event.stop(event);
+       case Event.KEY_ESC:
+         this.hide();
+         this.active = false;
+         Event.stop(event);
+         return;
+       case Event.KEY_LEFT:
+       case Event.KEY_RIGHT:
+         return;
+       case Event.KEY_UP:
+         this.markPrevious();
+         this.render();
+         if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
+         return;
+       case Event.KEY_DOWN:
+         this.markNext();
+         this.render();
+         if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
+         return;
+      }
+     else 
+       if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || 
+         (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return;
+
+    this.changed = true;
+    this.hasFocus = true;
+
+    if(this.observer) clearTimeout(this.observer);
+      this.observer = 
+        setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+  },
+
+  activate: function() {
+    this.changed = false;
+    this.hasFocus = true;
+    this.getUpdatedChoices();
+  },
+
+  onHover: function(event) {
+    var element = Event.findElement(event, 'LI');
+    if(this.index != element.autocompleteIndex) 
+    {
+        this.index = element.autocompleteIndex;
+        this.render();
+    }
+    Event.stop(event);
+  },
+  
+  onClick: function(event) {
+    var element = Event.findElement(event, 'LI');
+    this.index = element.autocompleteIndex;
+    this.selectEntry();
+    this.hide();
+  },
+  
+  onBlur: function(event) {
+    // needed to make click events working
+    setTimeout(this.hide.bind(this), 250);
+    this.hasFocus = false;
+    this.active = false;     
+  }, 
+  
+  render: function() {
+    if(this.entryCount > 0) {
+      for (var i = 0; i < this.entryCount; i++)
+        this.index==i ? 
+          Element.addClassName(this.getEntry(i),"selected") : 
+          Element.removeClassName(this.getEntry(i),"selected");
+        
+      if(this.hasFocus) { 
+        this.show();
+        this.active = true;
+      }
+    } else {
+      this.active = false;
+      this.hide();
+    }
+  },
+  
+  markPrevious: function() {
+    if(this.index > 0) this.index--
+      else this.index = this.entryCount-1;
+  },
+  
+  markNext: function() {
+    if(this.index < this.entryCount-1) this.index++
+      else this.index = 0;
+  },
+  
+  getEntry: function(index) {
+    return this.update.firstChild.childNodes[index];
+  },
+  
+  getCurrentEntry: function() {
+    return this.getEntry(this.index);
+  },
+  
+  selectEntry: function() {
+    this.active = false;
+    this.updateElement(this.getCurrentEntry());
+  },
+
+  updateElement: function(selectedElement) {
+    if (this.options.updateElement) {
+      this.options.updateElement(selectedElement);
+      return;
+    }
+    var value = '';
+    if (this.options.select) {
+      var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
+      if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+    } else
+      value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+    
+    var lastTokenPos = this.findLastToken();
+    if (lastTokenPos != -1) {
+      var newValue = this.element.value.substr(0, lastTokenPos + 1);
+      var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
+      if (whitespace)
+        newValue += whitespace[0];
+      this.element.value = newValue + value;
+    } else {
+      this.element.value = value;
+    }
+    this.element.focus();
+    
+    if (this.options.afterUpdateElement)
+      this.options.afterUpdateElement(this.element, selectedElement);
+  },
+
+  updateChoices: function(choices) {
+    if(!this.changed && this.hasFocus) {
+      this.update.innerHTML = choices;
+      Element.cleanWhitespace(this.update);
+      Element.cleanWhitespace(this.update.firstChild);
+
+      if(this.update.firstChild && this.update.firstChild.childNodes) {
+        this.entryCount = 
+          this.update.firstChild.childNodes.length;
+        for (var i = 0; i < this.entryCount; i++) {
+          var entry = this.getEntry(i);
+          entry.autocompleteIndex = i;
+          this.addObservers(entry);
+        }
+      } else { 
+        this.entryCount = 0;
+      }
+
+      this.stopIndicator();
+
+      this.index = 0;
+      this.render();
+    }
+  },
+
+  addObservers: function(element) {
+    Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+    Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+  },
+
+  onObserverEvent: function() {
+    this.changed = false;   
+    if(this.getToken().length>=this.options.minChars) {
+      this.startIndicator();
+      this.getUpdatedChoices();
+    } else {
+      this.active = false;
+      this.hide();
+    }
+  },
+
+  getToken: function() {
+    var tokenPos = this.findLastToken();
+    if (tokenPos != -1)
+      var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
+    else
+      var ret = this.element.value;
+
+    return /\n/.test(ret) ? '' : ret;
+  },
+
+  findLastToken: function() {
+    var lastTokenPos = -1;
+
+    for (var i=0; i<this.options.tokens.length; i++) {
+      var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
+      if (thisTokenPos > lastTokenPos)
+        lastTokenPos = thisTokenPos;
+    }
+    return lastTokenPos;
+  }
+}
+
+Ajax.Autocompleter = Class.create();
+Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
+  initialize: function(element, update, url, options) {
+    this.baseInitialize(element, update, options);
+    this.options.asynchronous  = true;
+    this.options.onComplete    = this.onComplete.bind(this);
+    this.options.defaultParams = this.options.parameters || null;
+    this.url                   = url;
+  },
+
+  getUpdatedChoices: function() {
+    entry = encodeURIComponent(this.options.paramName) + '=' + 
+      encodeURIComponent(this.getToken());
+
+    this.options.parameters = this.options.callback ?
+      this.options.callback(this.element, entry) : entry;
+
+    if(this.options.defaultParams) 
+      this.options.parameters += '&' + this.options.defaultParams;
+
+    new Ajax.Request(this.url, this.options);
+  },
+
+  onComplete: function(request) {
+    this.updateChoices(request.responseText);
+  }
+
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+//                    text only at the beginning of strings in the 
+//                    autocomplete array. Defaults to true, which will
+//                    match text at the beginning of any *word* in the
+//                    strings in the autocomplete array. If you want to
+//                    search anywhere in the string, additionally set
+//                    the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+//                   a partial match (unlike minChars, which defines
+//                   how many characters are required to do any match
+//                   at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+//                 Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector' 
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create();
+Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
+  initialize: function(element, update, array, options) {
+    this.baseInitialize(element, update, options);
+    this.options.array = array;
+  },
+
+  getUpdatedChoices: function() {
+    this.updateChoices(this.options.selector(this));
+  },
+
+  setOptions: function(options) {
+    this.options = Object.extend({
+      choices: 10,
+      partialSearch: true,
+      partialChars: 2,
+      ignoreCase: true,
+      fullSearch: false,
+      selector: function(instance) {
+        var ret       = []; // Beginning matches
+        var partial   = []; // Inside matches
+        var entry     = instance.getToken();
+        var count     = 0;
+
+        for (var i = 0; i < instance.options.array.length &&  
+          ret.length < instance.options.choices ; i++) { 
+
+          var elem = instance.options.array[i];
+          var foundPos = instance.options.ignoreCase ? 
+            elem.toLowerCase().indexOf(entry.toLowerCase()) : 
+            elem.indexOf(entry);
+
+          while (foundPos != -1) {
+            if (foundPos == 0 && elem.length != entry.length) { 
+              ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + 
+                elem.substr(entry.length) + "</li>");
+              break;
+            } else if (entry.length >= instance.options.partialChars && 
+              instance.options.partialSearch && foundPos != -1) {
+              if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+                partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+                  elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+                  foundPos + entry.length) + "</li>");
+                break;
+              }
+            }
+
+            foundPos = instance.options.ignoreCase ? 
+              elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : 
+              elem.indexOf(entry, foundPos + 1);
+
+          }
+        }
+        if (partial.length)
+          ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+        return "<ul>" + ret.join('') + "</ul>";
+      }
+    }, options || {});
+  }
+});
+
+// AJAX in-place editor
+//
+// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+  setTimeout(function() {
+    Field.activate(field);
+  }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create();
+Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
+Ajax.InPlaceEditor.prototype = {
+  initialize: function(element, url, options) {
+    this.url = url;
+    this.element = $(element);
+
+    this.options = Object.extend({
+      okButton: true,
+      okText: "ok",
+      cancelLink: true,
+      cancelText: "cancel",
+      savingText: "Saving...",
+      clickToEditText: "Click to edit",
+      okText: "ok",
+      rows: 1,
+      onComplete: function(transport, element) {
+        new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
+      },
+      onFailure: function(transport) {
+        alert("Error communicating with the server: " + transport.responseText.stripTags());
+      },
+      callback: function(form) {
+        return Form.serialize(form);
+      },
+      handleLineBreaks: true,
+      loadingText: 'Loading...',
+      savingClassName: 'inplaceeditor-saving',
+      loadingClassName: 'inplaceeditor-loading',
+      formClassName: 'inplaceeditor-form',
+      highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
+      highlightendcolor: "#FFFFFF",
+      externalControl: null,
+      submitOnBlur: false,
+      ajaxOptions: {},
+      evalScripts: false
+    }, options || {});
+
+    if(!this.options.formId && this.element.id) {
+      this.options.formId = this.element.id + "-inplaceeditor";
+      if ($(this.options.formId)) {
+        // there's already a form with that name, don't specify an id
+        this.options.formId = null;
+      }
+    }
+    
+    if (this.options.externalControl) {
+      this.options.externalControl = $(this.options.externalControl);
+    }
+    
+    this.originalBackground = Element.getStyle(this.element, 'background-color');
+    if (!this.originalBackground) {
+      this.originalBackground = "transparent";
+    }
+    
+    this.element.title = this.options.clickToEditText;
+    
+    this.onclickListener = this.enterEditMode.bindAsEventListener(this);
+    this.mouseoverListener = this.enterHover.bindAsEventListener(this);
+    this.mouseoutListener = this.leaveHover.bindAsEventListener(this);
+    Event.observe(this.element, 'click', this.onclickListener);
+    Event.observe(this.element, 'mouseover', this.mouseoverListener);
+    Event.observe(this.element, 'mouseout', this.mouseoutListener);
+    if (this.options.externalControl) {
+      Event.observe(this.options.externalControl, 'click', this.onclickListener);
+      Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener);
+      Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
+    }
+  },
+  enterEditMode: function(evt) {
+    if (this.saving) return;
+    if (this.editing) return;
+    this.editing = true;
+    this.onEnterEditMode();
+    if (this.options.externalControl) {
+      Element.hide(this.options.externalControl);
+    }
+    Element.hide(this.element);
+    this.createForm();
+    this.element.parentNode.insertBefore(this.form, this.element);
+    Field.scrollFreeActivate(this.editField);
+    // stop the event to avoid a page refresh in Safari
+    if (evt) {
+      Event.stop(evt);
+    }
+    return false;
+  },
+  createForm: function() {
+    this.form = document.createElement("form");
+    this.form.id = this.options.formId;
+    Element.addClassName(this.form, this.options.formClassName)
+    this.form.onsubmit = this.onSubmit.bind(this);
+
+    this.createEditField();
+
+    if (this.options.textarea) {
+      var br = document.createElement("br");
+      this.form.appendChild(br);
+    }
+
+    if (this.options.okButton) {
+      okButton = document.createElement("input");
+      okButton.type = "submit";
+      okButton.value = this.options.okText;
+      okButton.className = 'editor_ok_button';
+      this.form.appendChild(okButton);
+    }
+
+    if (this.options.cancelLink) {
+      cancelLink = document.createElement("a");
+      cancelLink.href = "#";
+      cancelLink.appendChild(document.createTextNode(this.options.cancelText));
+      cancelLink.onclick = this.onclickCancel.bind(this);
+      cancelLink.className = 'editor_cancel';      
+      this.form.appendChild(cancelLink);
+    }
+  },
+  hasHTMLLineBreaks: function(string) {
+    if (!this.options.handleLineBreaks) return false;
+    return string.match(/<br/i) || string.match(/<p>/i);
+  },
+  convertHTMLLineBreaks: function(string) {
+    return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, "");
+  },
+  createEditField: function() {
+    var text;
+    if(this.options.loadTextURL) {
+      text = this.options.loadingText;
+    } else {
+      text = this.getText();
+    }
+
+    var obj = this;
+    
+    if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
+      this.options.textarea = false;
+      var textField = document.createElement("input");
+      textField.obj = this;
+      textField.type = "text";
+      textField.name = "value";
+      textField.value = text;
+      textField.style.backgroundColor = this.options.highlightcolor;
+      textField.className = 'editor_field';
+      var size = this.options.size || this.options.cols || 0;
+      if (size != 0) textField.size = size;
+      if (this.options.submitOnBlur)
+        textField.onblur = this.onSubmit.bind(this);
+      this.editField = textField;
+    } else {
+      this.options.textarea = true;
+      var textArea = document.createElement("textarea");
+      textArea.obj = this;
+      textArea.name = "value";
+      textArea.value = this.convertHTMLLineBreaks(text);
+      textArea.rows = this.options.rows;
+      textArea.cols = this.options.cols || 40;
+      textArea.className = 'editor_field';      
+      if (this.options.submitOnBlur)
+        textArea.onblur = this.onSubmit.bind(this);
+      this.editField = textArea;
+    }
+    
+    if(this.options.loadTextURL) {
+      this.loadExternalText();
+    }
+    this.form.appendChild(this.editField);
+  },
+  getText: function() {
+    return this.element.innerHTML;
+  },
+  loadExternalText: function() {
+    Element.addClassName(this.form, this.options.loadingClassName);
+    this.editField.disabled = true;
+    new Ajax.Request(
+      this.options.loadTextURL,
+      Object.extend({
+        asynchronous: true,
+        onComplete: this.onLoadedExternalText.bind(this)
+      }, this.options.ajaxOptions)
+    );
+  },
+  onLoadedExternalText: function(transport) {
+    Element.removeClassName(this.form, this.options.loadingClassName);
+    this.editField.disabled = false;
+    this.editField.value = transport.responseText.stripTags();
+  },
+  onclickCancel: function() {
+    this.onComplete();
+    this.leaveEditMode();
+    return false;
+  },
+  onFailure: function(transport) {
+    this.options.onFailure(transport);
+    if (this.oldInnerHTML) {
+      this.element.innerHTML = this.oldInnerHTML;
+      this.oldInnerHTML = null;
+    }
+    return false;
+  },
+  onSubmit: function() {
+    // onLoading resets these so we need to save them away for the Ajax call
+    var form = this.form;
+    var value = this.editField.value;
+    
+    // do this first, sometimes the ajax call returns before we get a chance to switch on Saving...
+    // which means this will actually switch on Saving... *after* we've left edit mode causing Saving...
+    // to be displayed indefinitely
+    this.onLoading();
+    
+    if (this.options.evalScripts) {
+      new Ajax.Request(
+        this.url, Object.extend({
+          parameters: this.options.callback(form, value),
+          onComplete: this.onComplete.bind(this),
+          onFailure: this.onFailure.bind(this),
+          asynchronous:true, 
+          evalScripts:true
+        }, this.options.ajaxOptions));
+    } else  {
+      new Ajax.Updater(
+        { success: this.element,
+          // don't update on failure (this could be an option)
+          failure: null }, 
+        this.url, Object.extend({
+          parameters: this.options.callback(form, value),
+          onComplete: this.onComplete.bind(this),
+          onFailure: this.onFailure.bind(this)
+        }, this.options.ajaxOptions));
+    }
+    // stop the event to avoid a page refresh in Safari
+    if (arguments.length > 1) {
+      Event.stop(arguments[0]);
+    }
+    return false;
+  },
+  onLoading: function() {
+    this.saving = true;
+    this.removeForm();
+    this.leaveHover();
+    this.showSaving();
+  },
+  showSaving: function() {
+    this.oldInnerHTML = this.element.innerHTML;
+    this.element.innerHTML = this.options.savingText;
+    Element.addClassName(this.element, this.options.savingClassName);
+    this.element.style.backgroundColor = this.originalBackground;
+    Element.show(this.element);
+  },
+  removeForm: function() {
+    if(this.form) {
+      if (this.form.parentNode) Element.remove(this.form);
+      this.form = null;
+    }
+  },
+  enterHover: function() {
+    if (this.saving) return;
+    this.element.style.backgroundColor = this.options.highlightcolor;
+    if (this.effect) {
+      this.effect.cancel();
+    }
+    Element.addClassName(this.element, this.options.hoverClassName)
+  },
+  leaveHover: function() {
+    if (this.options.backgroundColor) {
+      this.element.style.backgroundColor = this.oldBackground;
+    }
+    Element.removeClassName(this.element, this.options.hoverClassName)
+    if (this.saving) return;
+    this.effect = new Effect.Highlight(this.element, {
+      startcolor: this.options.highlightcolor,
+      endcolor: this.options.highlightendcolor,
+      restorecolor: this.originalBackground
+    });
+  },
+  leaveEditMode: function() {
+    Element.removeClassName(this.element, this.options.savingClassName);
+    this.removeForm();
+    this.leaveHover();
+    this.element.style.backgroundColor = this.originalBackground;
+    Element.show(this.element);
+    if (this.options.externalControl) {
+      Element.show(this.options.externalControl);
+    }
+    this.editing = false;
+    this.saving = false;
+    this.oldInnerHTML = null;
+    this.onLeaveEditMode();
+  },
+  onComplete: function(transport) {
+    this.leaveEditMode();
+    this.options.onComplete.bind(this)(transport, this.element);
+  },
+  onEnterEditMode: function() {},
+  onLeaveEditMode: function() {},
+  dispose: function() {
+    if (this.oldInnerHTML) {
+      this.element.innerHTML = this.oldInnerHTML;
+    }
+    this.leaveEditMode();
+    Event.stopObserving(this.element, 'click', this.onclickListener);
+    Event.stopObserving(this.element, 'mouseover', this.mouseoverListener);
+    Event.stopObserving(this.element, 'mouseout', this.mouseoutListener);
+    if (this.options.externalControl) {
+      Event.stopObserving(this.options.externalControl, 'click', this.onclickListener);
+      Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener);
+      Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener);
+    }
+  }
+};
+
+Ajax.InPlaceCollectionEditor = Class.create();
+Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype);
+Object.extend(Ajax.InPlaceCollectionEditor.prototype, {
+  createEditField: function() {
+    if (!this.cached_selectTag) {
+      var selectTag = document.createElement("select");
+      var collection = this.options.collection || [];
+      var optionTag;
+      collection.each(function(e,i) {
+        optionTag = document.createElement("option");
+        optionTag.value = (e instanceof Array) ? e[0] : e;
+        if(this.options.value==optionTag.value) optionTag.selected = true;
+        optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e));
+        selectTag.appendChild(optionTag);
+      }.bind(this));
+      this.cached_selectTag = selectTag;
+    }
+
+    this.editField = this.cached_selectTag;
+    if(this.options.loadTextURL) this.loadExternalText();
+    this.form.appendChild(this.editField);
+    this.options.callback = function(form, value) {
+      return "value=" + encodeURIComponent(value);
+    }
+  }
+});
+
+// Delayed observer, like Form.Element.Observer, 
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create();
+Form.Element.DelayedObserver.prototype = {
+  initialize: function(element, delay, callback) {
+    this.delay     = delay || 0.5;
+    this.element   = $(element);
+    this.callback  = callback;
+    this.timer     = null;
+    this.lastValue = $F(this.element); 
+    Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+  },
+  delayedListener: function(event) {
+    if(this.lastValue == $F(this.element)) return;
+    if(this.timer) clearTimeout(this.timer);
+    this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+    this.lastValue = $F(this.element);
+  },
+  onTimerEvent: function() {
+    this.timer = null;
+    this.callback(this.element, $F(this.element));
+  }
+};
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/dragdrop.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/dragdrop.js
new file mode 100644 (file)
index 0000000..be2a30f
--- /dev/null
@@ -0,0 +1,915 @@
+// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//           (c) 2005 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+// 
+// See scriptaculous.js for full license.
+
+/*--------------------------------------------------------------------------*/
+
+var Droppables = {
+  drops: [],
+
+  remove: function(element) {
+    this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+  },
+
+  add: function(element) {
+    element = $(element);
+    var options = Object.extend({
+      greedy:     true,
+      hoverclass: null,
+      tree:       false
+    }, arguments[1] || {});
+
+    // cache containers
+    if(options.containment) {
+      options._containers = [];
+      var containment = options.containment;
+      if((typeof containment == 'object') && 
+        (containment.constructor == Array)) {
+        containment.each( function(c) { options._containers.push($(c)) });
+      } else {
+        options._containers.push($(containment));
+      }
+    }
+    
+    if(options.accept) options.accept = [options.accept].flatten();
+
+    Element.makePositioned(element); // fix IE
+    options.element = element;
+
+    this.drops.push(options);
+  },
+  
+  findDeepestChild: function(drops) {
+    deepest = drops[0];
+      
+    for (i = 1; i < drops.length; ++i)
+      if (Element.isParent(drops[i].element, deepest.element))
+        deepest = drops[i];
+    
+    return deepest;
+  },
+
+  isContained: function(element, drop) {
+    var containmentNode;
+    if(drop.tree) {
+      containmentNode = element.treeNode; 
+    } else {
+      containmentNode = element.parentNode;
+    }
+    return drop._containers.detect(function(c) { return containmentNode == c });
+  },
+  
+  isAffected: function(point, element, drop) {
+    return (
+      (drop.element!=element) &&
+      ((!drop._containers) ||
+        this.isContained(element, drop)) &&
+      ((!drop.accept) ||
+        (Element.classNames(element).detect( 
+          function(v) { return drop.accept.include(v) } ) )) &&
+      Position.within(drop.element, point[0], point[1]) );
+  },
+
+  deactivate: function(drop) {
+    if(drop.hoverclass)
+      Element.removeClassName(drop.element, drop.hoverclass);
+    this.last_active = null;
+  },
+
+  activate: function(drop) {
+    if(drop.hoverclass)
+      Element.addClassName(drop.element, drop.hoverclass);
+    this.last_active = drop;
+  },
+
+  show: function(point, element) {
+    if(!this.drops.length) return;
+    var affected = [];
+    
+    if(this.last_active) this.deactivate(this.last_active);
+    this.drops.each( function(drop) {
+      if(Droppables.isAffected(point, element, drop))
+        affected.push(drop);
+    });
+        
+    if(affected.length>0) {
+      drop = Droppables.findDeepestChild(affected);
+      Position.within(drop.element, point[0], point[1]);
+      if(drop.onHover)
+        drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+      
+      Droppables.activate(drop);
+    }
+  },
+
+  fire: function(event, element) {
+    if(!this.last_active) return;
+    Position.prepare();
+
+    if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+      if (this.last_active.onDrop) 
+        this.last_active.onDrop(element, this.last_active.element, event);
+  },
+
+  reset: function() {
+    if(this.last_active)
+      this.deactivate(this.last_active);
+  }
+}
+
+var Draggables = {
+  drags: [],
+  observers: [],
+  
+  register: function(draggable) {
+    if(this.drags.length == 0) {
+      this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
+      this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+      this.eventKeypress  = this.keyPress.bindAsEventListener(this);
+      
+      Event.observe(document, "mouseup", this.eventMouseUp);
+      Event.observe(document, "mousemove", this.eventMouseMove);
+      Event.observe(document, "keypress", this.eventKeypress);
+    }
+    this.drags.push(draggable);
+  },
+  
+  unregister: function(draggable) {
+    this.drags = this.drags.reject(function(d) { return d==draggable });
+    if(this.drags.length == 0) {
+      Event.stopObserving(document, "mouseup", this.eventMouseUp);
+      Event.stopObserving(document, "mousemove", this.eventMouseMove);
+      Event.stopObserving(document, "keypress", this.eventKeypress);
+    }
+  },
+  
+  activate: function(draggable) {
+    window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+    this.activeDraggable = draggable;
+  },
+  
+  deactivate: function() {
+    this.activeDraggable = null;
+  },
+  
+  updateDrag: function(event) {
+    if(!this.activeDraggable) return;
+    var pointer = [Event.pointerX(event), Event.pointerY(event)];
+    // Mozilla-based browsers fire successive mousemove events with
+    // the same coordinates, prevent needless redrawing (moz bug?)
+    if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+    this._lastPointer = pointer;
+    this.activeDraggable.updateDrag(event, pointer);
+  },
+  
+  endDrag: function(event) {
+    if(!this.activeDraggable) return;
+    this._lastPointer = null;
+    this.activeDraggable.endDrag(event);
+    this.activeDraggable = null;
+  },
+  
+  keyPress: function(event) {
+    if(this.activeDraggable)
+      this.activeDraggable.keyPress(event);
+  },
+  
+  addObserver: function(observer) {
+    this.observers.push(observer);
+    this._cacheObserverCallbacks();
+  },
+  
+  removeObserver: function(element) {  // element instead of observer fixes mem leaks
+    this.observers = this.observers.reject( function(o) { return o.element==element });
+    this._cacheObserverCallbacks();
+  },
+  
+  notify: function(eventName, draggable, event) {  // 'onStart', 'onEnd', 'onDrag'
+    if(this[eventName+'Count'] > 0)
+      this.observers.each( function(o) {
+        if(o[eventName]) o[eventName](eventName, draggable, event);
+      });
+  },
+  
+  _cacheObserverCallbacks: function() {
+    ['onStart','onEnd','onDrag'].each( function(eventName) {
+      Draggables[eventName+'Count'] = Draggables.observers.select(
+        function(o) { return o[eventName]; }
+      ).length;
+    });
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create();
+Draggable.prototype = {
+  initialize: function(element) {
+    var options = Object.extend({
+      handle: false,
+      starteffect: function(element) {
+        element._opacity = Element.getOpacity(element); 
+        new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); 
+      },
+      reverteffect: function(element, top_offset, left_offset) {
+        var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+        element._revert = new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur});
+      },
+      endeffect: function(element) {
+        var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0
+        new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity}); 
+      },
+      zindex: 1000,
+      revert: false,
+      scroll: false,
+      scrollSensitivity: 20,
+      scrollSpeed: 15,
+      snap: false   // false, or xy or [x,y] or function(x,y){ return [x,y] }
+    }, arguments[1] || {});
+
+    this.element = $(element);
+    
+    if(options.handle && (typeof options.handle == 'string')) {
+      var h = Element.childrenWithClassName(this.element, options.handle, true);
+      if(h.length>0) this.handle = h[0];
+    }
+    if(!this.handle) this.handle = $(options.handle);
+    if(!this.handle) this.handle = this.element;
+    
+    if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML)
+      options.scroll = $(options.scroll);
+
+    Element.makePositioned(this.element); // fix IE    
+
+    this.delta    = this.currentDelta();
+    this.options  = options;
+    this.dragging = false;   
+
+    this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+    Event.observe(this.handle, "mousedown", this.eventMouseDown);
+    
+    Draggables.register(this);
+  },
+  
+  destroy: function() {
+    Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+    Draggables.unregister(this);
+  },
+  
+  currentDelta: function() {
+    return([
+      parseInt(Element.getStyle(this.element,'left') || '0'),
+      parseInt(Element.getStyle(this.element,'top') || '0')]);
+  },
+  
+  initDrag: function(event) {
+    if(Event.isLeftClick(event)) {    
+      // abort on form elements, fixes a Firefox issue
+      var src = Event.element(event);
+      if(src.tagName && (
+        src.tagName=='INPUT' ||
+        src.tagName=='SELECT' ||
+        src.tagName=='OPTION' ||
+        src.tagName=='BUTTON' ||
+        src.tagName=='TEXTAREA')) return;
+        
+      if(this.element._revert) {
+        this.element._revert.cancel();
+        this.element._revert = null;
+      }
+      
+      var pointer = [Event.pointerX(event), Event.pointerY(event)];
+      var pos     = Position.cumulativeOffset(this.element);
+      this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+      
+      Draggables.activate(this);
+      Event.stop(event);
+    }
+  },
+  
+  startDrag: function(event) {
+    this.dragging = true;
+    
+    if(this.options.zindex) {
+      this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+      this.element.style.zIndex = this.options.zindex;
+    }
+    
+    if(this.options.ghosting) {
+      this._clone = this.element.cloneNode(true);
+      Position.absolutize(this.element);
+      this.element.parentNode.insertBefore(this._clone, this.element);
+    }
+    
+    if(this.options.scroll) {
+      if (this.options.scroll == window) {
+        var where = this._getWindowScroll(this.options.scroll);
+        this.originalScrollLeft = where.left;
+        this.originalScrollTop = where.top;
+      } else {
+        this.originalScrollLeft = this.options.scroll.scrollLeft;
+        this.originalScrollTop = this.options.scroll.scrollTop;
+      }
+    }
+    
+    Draggables.notify('onStart', this, event);
+    if(this.options.starteffect) this.options.starteffect(this.element);
+  },
+  
+  updateDrag: function(event, pointer) {
+    if(!this.dragging) this.startDrag(event);
+    Position.prepare();
+    Droppables.show(pointer, this.element);
+    Draggables.notify('onDrag', this, event);
+    this.draw(pointer);
+    if(this.options.change) this.options.change(this);
+    
+    if(this.options.scroll) {
+      this.stopScrolling();
+      
+      var p;
+      if (this.options.scroll == window) {
+        with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+      } else {
+        p = Position.page(this.options.scroll);
+        p[0] += this.options.scroll.scrollLeft;
+        p[1] += this.options.scroll.scrollTop;
+        p.push(p[0]+this.options.scroll.offsetWidth);
+        p.push(p[1]+this.options.scroll.offsetHeight);
+      }
+      var speed = [0,0];
+      if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+      if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+      if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+      if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+      this.startScrolling(speed);
+    }
+    
+    // fix AppleWebKit rendering
+    if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
+    
+    Event.stop(event);
+  },
+  
+  finishDrag: function(event, success) {
+    this.dragging = false;
+
+    if(this.options.ghosting) {
+      Position.relativize(this.element);
+      Element.remove(this._clone);
+      this._clone = null;
+    }
+
+    if(success) Droppables.fire(event, this.element);
+    Draggables.notify('onEnd', this, event);
+
+    var revert = this.options.revert;
+    if(revert && typeof revert == 'function') revert = revert(this.element);
+    
+    var d = this.currentDelta();
+    if(revert && this.options.reverteffect) {
+      this.options.reverteffect(this.element, 
+        d[1]-this.delta[1], d[0]-this.delta[0]);
+    } else {
+      this.delta = d;
+    }
+
+    if(this.options.zindex)
+      this.element.style.zIndex = this.originalZ;
+
+    if(this.options.endeffect) 
+      this.options.endeffect(this.element);
+
+    Draggables.deactivate(this);
+    Droppables.reset();
+  },
+  
+  keyPress: function(event) {
+    if(event.keyCode!=Event.KEY_ESC) return;
+    this.finishDrag(event, false);
+    Event.stop(event);
+  },
+  
+  endDrag: function(event) {
+    if(!this.dragging) return;
+    this.stopScrolling();
+    this.finishDrag(event, true);
+    Event.stop(event);
+  },
+  
+  draw: function(point) {
+    var pos = Position.cumulativeOffset(this.element);
+    var d = this.currentDelta();
+    pos[0] -= d[0]; pos[1] -= d[1];
+    
+    if(this.options.scroll && (this.options.scroll != window)) {
+      pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+      pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+    }
+    
+    var p = [0,1].map(function(i){ 
+      return (point[i]-pos[i]-this.offset[i]) 
+    }.bind(this));
+    
+    if(this.options.snap) {
+      if(typeof this.options.snap == 'function') {
+        p = this.options.snap(p[0],p[1],this);
+      } else {
+      if(this.options.snap instanceof Array) {
+        p = p.map( function(v, i) {
+          return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this))
+      } else {
+        p = p.map( function(v) {
+          return Math.round(v/this.options.snap)*this.options.snap }.bind(this))
+      }
+    }}
+    
+    var style = this.element.style;
+    if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+      style.left = p[0] + "px";
+    if((!this.options.constraint) || (this.options.constraint=='vertical'))
+      style.top  = p[1] + "px";
+    if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+  },
+  
+  stopScrolling: function() {
+    if(this.scrollInterval) {
+      clearInterval(this.scrollInterval);
+      this.scrollInterval = null;
+      Draggables._lastScrollPointer = null;
+    }
+  },
+  
+  startScrolling: function(speed) {
+    this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+    this.lastScrolled = new Date();
+    this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+  },
+  
+  scroll: function() {
+    var current = new Date();
+    var delta = current - this.lastScrolled;
+    this.lastScrolled = current;
+    if(this.options.scroll == window) {
+      with (this._getWindowScroll(this.options.scroll)) {
+        if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+          var d = delta / 1000;
+          this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+        }
+      }
+    } else {
+      this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+      this.options.scroll.scrollTop  += this.scrollSpeed[1] * delta / 1000;
+    }
+    
+    Position.prepare();
+    Droppables.show(Draggables._lastPointer, this.element);
+    Draggables.notify('onDrag', this);
+    Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+    Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+    Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+    if (Draggables._lastScrollPointer[0] < 0)
+      Draggables._lastScrollPointer[0] = 0;
+    if (Draggables._lastScrollPointer[1] < 0)
+      Draggables._lastScrollPointer[1] = 0;
+    this.draw(Draggables._lastScrollPointer);
+    
+    if(this.options.change) this.options.change(this);
+  },
+  
+  _getWindowScroll: function(w) {
+    var T, L, W, H;
+    with (w.document) {
+      if (w.document.documentElement && documentElement.scrollTop) {
+        T = documentElement.scrollTop;
+        L = documentElement.scrollLeft;
+      } else if (w.document.body) {
+        T = body.scrollTop;
+        L = body.scrollLeft;
+      }
+      if (w.innerWidth) {
+        W = w.innerWidth;
+        H = w.innerHeight;
+      } else if (w.document.documentElement && documentElement.clientWidth) {
+        W = documentElement.clientWidth;
+        H = documentElement.clientHeight;
+      } else {
+        W = body.offsetWidth;
+        H = body.offsetHeight
+      }
+    }
+    return { top: T, left: L, width: W, height: H };
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create();
+SortableObserver.prototype = {
+  initialize: function(element, observer) {
+    this.element   = $(element);
+    this.observer  = observer;
+    this.lastValue = Sortable.serialize(this.element);
+  },
+  
+  onStart: function() {
+    this.lastValue = Sortable.serialize(this.element);
+  },
+  
+  onEnd: function() {
+    Sortable.unmark();
+    if(this.lastValue != Sortable.serialize(this.element))
+      this.observer(this.element)
+  }
+}
+
+var Sortable = {
+  sortables: {},
+  
+  _findRootElement: function(element) {
+    while (element.tagName != "BODY") {  
+      if(element.id && Sortable.sortables[element.id]) return element;
+      element = element.parentNode;
+    }
+  },
+
+  options: function(element) {
+    element = Sortable._findRootElement($(element));
+    if(!element) return;
+    return Sortable.sortables[element.id];
+  },
+  
+  destroy: function(element){
+    var s = Sortable.options(element);
+    
+    if(s) {
+      Draggables.removeObserver(s.element);
+      s.droppables.each(function(d){ Droppables.remove(d) });
+      s.draggables.invoke('destroy');
+      
+      delete Sortable.sortables[s.element.id];
+    }
+  },
+
+  create: function(element) {
+    element = $(element);
+    var options = Object.extend({ 
+      element:     element,
+      tag:         'li',       // assumes li children, override with tag: 'tagname'
+      dropOnEmpty: false,
+      tree:        false,
+      treeTag:     'ul',
+      overlap:     'vertical', // one of 'vertical', 'horizontal'
+      constraint:  'vertical', // one of 'vertical', 'horizontal', false
+      containment: element,    // also takes array of elements (or id's); or false
+      handle:      false,      // or a CSS class
+      only:        false,
+      hoverclass:  null,
+      ghosting:    false,
+      scroll:      false,
+      scrollSensitivity: 20,
+      scrollSpeed: 15,
+      format:      /^[^_]*_(.*)$/,
+      onChange:    Prototype.emptyFunction,
+      onUpdate:    Prototype.emptyFunction
+    }, arguments[1] || {});
+
+    // clear any old sortable with same element
+    this.destroy(element);
+
+    // build options for the draggables
+    var options_for_draggable = {
+      revert:      true,
+      scroll:      options.scroll,
+      scrollSpeed: options.scrollSpeed,
+      scrollSensitivity: options.scrollSensitivity,
+      ghosting:    options.ghosting,
+      constraint:  options.constraint,
+      handle:      options.handle };
+
+    if(options.starteffect)
+      options_for_draggable.starteffect = options.starteffect;
+
+    if(options.reverteffect)
+      options_for_draggable.reverteffect = options.reverteffect;
+    else
+      if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+        element.style.top  = 0;
+        element.style.left = 0;
+      };
+
+    if(options.endeffect)
+      options_for_draggable.endeffect = options.endeffect;
+
+    if(options.zindex)
+      options_for_draggable.zindex = options.zindex;
+
+    // build options for the droppables  
+    var options_for_droppable = {
+      overlap:     options.overlap,
+      containment: options.containment,
+      tree:        options.tree,
+      hoverclass:  options.hoverclass,
+      onHover:     Sortable.onHover
+      //greedy:      !options.dropOnEmpty
+    }
+    
+    var options_for_tree = {
+      onHover:      Sortable.onEmptyHover,
+      overlap:      options.overlap,
+      containment:  options.containment,
+      hoverclass:   options.hoverclass
+    }
+
+    // fix for gecko engine
+    Element.cleanWhitespace(element); 
+
+    options.draggables = [];
+    options.droppables = [];
+
+    // drop on empty handling
+    if(options.dropOnEmpty || options.tree) {
+      Droppables.add(element, options_for_tree);
+      options.droppables.push(element);
+    }
+
+    (this.findElements(element, options) || []).each( function(e) {
+      // handles are per-draggable
+      var handle = options.handle ? 
+        Element.childrenWithClassName(e, options.handle)[0] : e;    
+      options.draggables.push(
+        new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+      Droppables.add(e, options_for_droppable);
+      if(options.tree) e.treeNode = element;
+      options.droppables.push(e);      
+    });
+    
+    if(options.tree) {
+      (Sortable.findTreeElements(element, options) || []).each( function(e) {
+        Droppables.add(e, options_for_tree);
+        e.treeNode = element;
+        options.droppables.push(e);
+      });
+    }
+
+    // keep reference
+    this.sortables[element.id] = options;
+
+    // for onupdate
+    Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+  },
+
+  // return all suitable-for-sortable elements in a guaranteed order
+  findElements: function(element, options) {
+    return Element.findChildren(
+      element, options.only, options.tree ? true : false, options.tag);
+  },
+  
+  findTreeElements: function(element, options) {
+    return Element.findChildren(
+      element, options.only, options.tree ? true : false, options.treeTag);
+  },
+
+  onHover: function(element, dropon, overlap) {
+    if(Element.isParent(dropon, element)) return;
+
+    if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+      return;
+    } else if(overlap>0.5) {
+      Sortable.mark(dropon, 'before');
+      if(dropon.previousSibling != element) {
+        var oldParentNode = element.parentNode;
+        element.style.visibility = "hidden"; // fix gecko rendering
+        dropon.parentNode.insertBefore(element, dropon);
+        if(dropon.parentNode!=oldParentNode) 
+          Sortable.options(oldParentNode).onChange(element);
+        Sortable.options(dropon.parentNode).onChange(element);
+      }
+    } else {
+      Sortable.mark(dropon, 'after');
+      var nextElement = dropon.nextSibling || null;
+      if(nextElement != element) {
+        var oldParentNode = element.parentNode;
+        element.style.visibility = "hidden"; // fix gecko rendering
+        dropon.parentNode.insertBefore(element, nextElement);
+        if(dropon.parentNode!=oldParentNode) 
+          Sortable.options(oldParentNode).onChange(element);
+        Sortable.options(dropon.parentNode).onChange(element);
+      }
+    }
+  },
+  
+  onEmptyHover: function(element, dropon, overlap) {
+    var oldParentNode = element.parentNode;
+    var droponOptions = Sortable.options(dropon);
+        
+    if(!Element.isParent(dropon, element)) {
+      var index;
+      
+      var children = Sortable.findElements(dropon, {tag: droponOptions.tag});
+      var child = null;
+            
+      if(children) {
+        var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+        
+        for (index = 0; index < children.length; index += 1) {
+          if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+            offset -= Element.offsetSize (children[index], droponOptions.overlap);
+          } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+            child = index + 1 < children.length ? children[index + 1] : null;
+            break;
+          } else {
+            child = children[index];
+            break;
+          }
+        }
+      }
+      
+      dropon.insertBefore(element, child);
+      
+      Sortable.options(oldParentNode).onChange(element);
+      droponOptions.onChange(element);
+    }
+  },
+
+  unmark: function() {
+    if(Sortable._marker) Element.hide(Sortable._marker);
+  },
+
+  mark: function(dropon, position) {
+    // mark on ghosting only
+    var sortable = Sortable.options(dropon.parentNode);
+    if(sortable && !sortable.ghosting) return; 
+
+    if(!Sortable._marker) {
+      Sortable._marker = $('dropmarker') || document.createElement('DIV');
+      Element.hide(Sortable._marker);
+      Element.addClassName(Sortable._marker, 'dropmarker');
+      Sortable._marker.style.position = 'absolute';
+      document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+    }    
+    var offsets = Position.cumulativeOffset(dropon);
+    Sortable._marker.style.left = offsets[0] + 'px';
+    Sortable._marker.style.top = offsets[1] + 'px';
+    
+    if(position=='after')
+      if(sortable.overlap == 'horizontal') 
+        Sortable._marker.style.left = (offsets[0]+dropon.clientWidth) + 'px';
+      else
+        Sortable._marker.style.top = (offsets[1]+dropon.clientHeight) + 'px';
+    
+    Element.show(Sortable._marker);
+  },
+  
+  _tree: function(element, options, parent) {
+    var children = Sortable.findElements(element, options) || [];
+  
+    for (var i = 0; i < children.length; ++i) {
+      var match = children[i].id.match(options.format);
+
+      if (!match) continue;
+      
+      var child = {
+        id: encodeURIComponent(match ? match[1] : null),
+        element: element,
+        parent: parent,
+        children: new Array,
+        position: parent.children.length,
+        container: Sortable._findChildrenElement(children[i], options.treeTag.toUpperCase())
+      }
+      
+      /* Get the element containing the children and recurse over it */
+      if (child.container)
+        this._tree(child.container, options, child)
+      
+      parent.children.push (child);
+    }
+
+    return parent; 
+  },
+
+  /* Finds the first element of the given tag type within a parent element.
+    Used for finding the first LI[ST] within a L[IST]I[TEM].*/
+  _findChildrenElement: function (element, containerTag) {
+    if (element && element.hasChildNodes)
+      for (var i = 0; i < element.childNodes.length; ++i)
+        if (element.childNodes[i].tagName == containerTag)
+          return element.childNodes[i];
+  
+    return null;
+  },
+
+  tree: function(element) {
+    element = $(element);
+    var sortableOptions = this.options(element);
+    var options = Object.extend({
+      tag: sortableOptions.tag,
+      treeTag: sortableOptions.treeTag,
+      only: sortableOptions.only,
+      name: element.id,
+      format: sortableOptions.format
+    }, arguments[1] || {});
+    
+    var root = {
+      id: null,
+      parent: null,
+      children: new Array,
+      container: element,
+      position: 0
+    }
+    
+    return Sortable._tree (element, options, root);
+  },
+
+  /* Construct a [i] index for a particular node */
+  _constructIndex: function(node) {
+    var index = '';
+    do {
+      if (node.id) index = '[' + node.position + ']' + index;
+    } while ((node = node.parent) != null);
+    return index;
+  },
+
+  sequence: function(element) {
+    element = $(element);
+    var options = Object.extend(this.options(element), arguments[1] || {});
+    
+    return $(this.findElements(element, options) || []).map( function(item) {
+      return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+    });
+  },
+
+  setSequence: function(element, new_sequence) {
+    element = $(element);
+    var options = Object.extend(this.options(element), arguments[2] || {});
+    
+    var nodeMap = {};
+    this.findElements(element, options).each( function(n) {
+        if (n.id.match(options.format))
+            nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+        n.parentNode.removeChild(n);
+    });
+   
+    new_sequence.each(function(ident) {
+      var n = nodeMap[ident];
+      if (n) {
+        n[1].appendChild(n[0]);
+        delete nodeMap[ident];
+      }
+    });
+  },
+  
+  serialize: function(element) {
+    element = $(element);
+    var options = Object.extend(Sortable.options(element), arguments[1] || {});
+    var name = encodeURIComponent(
+      (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+    
+    if (options.tree) {
+      return Sortable.tree(element, arguments[1]).children.map( function (item) {
+        return [name + Sortable._constructIndex(item) + "=" + 
+                encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+      }).flatten().join('&');
+    } else {
+      return Sortable.sequence(element, arguments[1]).map( function(item) {
+        return name + "[]=" + encodeURIComponent(item);
+      }).join('&');
+    }
+  }
+}
+
+/* Returns true if child is contained within element */
+Element.isParent = function(child, element) {
+  if (!child.parentNode || child == element) return false;
+
+  if (child.parentNode == element) return true;
+
+  return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {    
+  if(!element.hasChildNodes()) return null;
+  tagName = tagName.toUpperCase();
+  if(only) only = [only].flatten();
+  var elements = [];
+  $A(element.childNodes).each( function(e) {
+    if(e.tagName && e.tagName.toUpperCase()==tagName &&
+      (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+        elements.push(e);
+    if(recursive) {
+      var grandchildren = Element.findChildren(e, only, recursive, tagName);
+      if(grandchildren) elements.push(grandchildren);
+    }
+  });
+
+  return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+  if (type == 'vertical' || type == 'height')
+    return element.offsetHeight;
+  else
+    return element.offsetWidth;
+}
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/effects.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/effects.js
new file mode 100644 (file)
index 0000000..0864323
--- /dev/null
@@ -0,0 +1,958 @@
+// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+//  Justin Palmer (http://encytemedia.com/)
+//  Mark Pilgrim (http://diveintomark.org/)
+//  Martin Bialasinki
+// 
+// See scriptaculous.js for full license.  
+
+// converts rgb() and #xxx to #xxxxxx format,  
+// returns self (or first argument) if not convertable  
+String.prototype.parseColor = function() {  
+  var color = '#';  
+  if(this.slice(0,4) == 'rgb(') {  
+    var cols = this.slice(4,this.length-1).split(',');  
+    var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);  
+  } else {  
+    if(this.slice(0,1) == '#') {  
+      if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();  
+      if(this.length==7) color = this.toLowerCase();  
+    }  
+  }  
+  return(color.length==7 ? color : (arguments[0] || this));  
+}
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {  
+  return $A($(element).childNodes).collect( function(node) {
+    return (node.nodeType==3 ? node.nodeValue : 
+      (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+  }).flatten().join('');
+}
+
+Element.collectTextNodesIgnoreClass = function(element, className) {  
+  return $A($(element).childNodes).collect( function(node) {
+    return (node.nodeType==3 ? node.nodeValue : 
+      ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? 
+        Element.collectTextNodesIgnoreClass(node, className) : ''));
+  }).flatten().join('');
+}
+
+Element.setContentZoom = function(element, percent) {
+  element = $(element);  
+  Element.setStyle(element, {fontSize: (percent/100) + 'em'});   
+  if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
+}
+
+Element.getOpacity = function(element){  
+  var opacity;
+  if (opacity = Element.getStyle(element, 'opacity'))  
+    return parseFloat(opacity);  
+  if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/))  
+    if(opacity[1]) return parseFloat(opacity[1]) / 100;  
+  return 1.0;  
+}
+
+Element.setOpacity = function(element, value){  
+  element= $(element);  
+  if (value == 1){
+    Element.setStyle(element, { opacity: 
+      (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 
+      0.999999 : null });
+    if(/MSIE/.test(navigator.userAgent))  
+      Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')});  
+  } else {  
+    if(value < 0.00001) value = 0;  
+    Element.setStyle(element, {opacity: value});
+    if(/MSIE/.test(navigator.userAgent))  
+     Element.setStyle(element, 
+       { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') +
+                 'alpha(opacity='+value*100+')' });  
+  }
+}  
+Element.getInlineOpacity = function(element){  
+  return $(element).style.opacity || '';
+}  
+
+Element.childrenWithClassName = function(element, className, findFirst) {
+  var classNameRegExp = new RegExp("(^|\\s)" + className + "(\\s|$)");
+  var results = $A($(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) { 
+    return (c.className && c.className.match(classNameRegExp));
+  });
+  if(!results) results = [];
+  return results;
+}
+
+Element.forceRerendering = function(element) {
+  try {
+    element = $(element);
+    var n = document.createTextNode(' ');
+    element.appendChild(n);
+    element.removeChild(n);
+  } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Array.prototype.call = function() {
+  var args = arguments;
+  this.each(function(f){ f.apply(this, args) });
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+  tagifyText: function(element) {
+    var tagifyStyle = 'position:relative';
+    if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1';
+    element = $(element);
+    $A(element.childNodes).each( function(child) {
+      if(child.nodeType==3) {
+        child.nodeValue.toArray().each( function(character) {
+          element.insertBefore(
+            Builder.node('span',{style: tagifyStyle},
+              character == ' ' ? String.fromCharCode(160) : character), 
+              child);
+        });
+        Element.remove(child);
+      }
+    });
+  },
+  multiple: function(element, effect) {
+    var elements;
+    if(((typeof element == 'object') || 
+        (typeof element == 'function')) && 
+       (element.length))
+      elements = element;
+    else
+      elements = $(element).childNodes;
+      
+    var options = Object.extend({
+      speed: 0.1,
+      delay: 0.0
+    }, arguments[2] || {});
+    var masterDelay = options.delay;
+
+    $A(elements).each( function(element, index) {
+      new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+    });
+  },
+  PAIRS: {
+    'slide':  ['SlideDown','SlideUp'],
+    'blind':  ['BlindDown','BlindUp'],
+    'appear': ['Appear','Fade']
+  },
+  toggle: function(element, effect) {
+    element = $(element);
+    effect = (effect || 'appear').toLowerCase();
+    var options = Object.extend({
+      queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+    }, arguments[2] || {});
+    Effect[element.visible() ? 
+      Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+  }
+};
+
+var Effect2 = Effect; // deprecated
+
+/* ------------- transitions ------------- */
+
+Effect.Transitions = {}
+
+Effect.Transitions.linear = function(pos) {
+  return pos;
+}
+Effect.Transitions.sinoidal = function(pos) {
+  return (-Math.cos(pos*Math.PI)/2) + 0.5;
+}
+Effect.Transitions.reverse  = function(pos) {
+  return 1-pos;
+}
+Effect.Transitions.flicker = function(pos) {
+  return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+}
+Effect.Transitions.wobble = function(pos) {
+  return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+}
+Effect.Transitions.pulse = function(pos) {
+  return (Math.floor(pos*10) % 2 == 0 ? 
+    (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10)));
+}
+Effect.Transitions.none = function(pos) {
+  return 0;
+}
+Effect.Transitions.full = function(pos) {
+  return 1;
+}
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create();
+Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
+  initialize: function() {
+    this.effects  = [];
+    this.interval = null;
+  },
+  _each: function(iterator) {
+    this.effects._each(iterator);
+  },
+  add: function(effect) {
+    var timestamp = new Date().getTime();
+    
+    var position = (typeof effect.options.queue == 'string') ? 
+      effect.options.queue : effect.options.queue.position;
+    
+    switch(position) {
+      case 'front':
+        // move unstarted effects after this effect  
+        this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+            e.startOn  += effect.finishOn;
+            e.finishOn += effect.finishOn;
+          });
+        break;
+      case 'end':
+        // start effect after last queued effect has finished
+        timestamp = this.effects.pluck('finishOn').max() || timestamp;
+        break;
+    }
+    
+    effect.startOn  += timestamp;
+    effect.finishOn += timestamp;
+
+    if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+      this.effects.push(effect);
+    
+    if(!this.interval) 
+      this.interval = setInterval(this.loop.bind(this), 40);
+  },
+  remove: function(effect) {
+    this.effects = this.effects.reject(function(e) { return e==effect });
+    if(this.effects.length == 0) {
+      clearInterval(this.interval);
+      this.interval = null;
+    }
+  },
+  loop: function() {
+    var timePos = new Date().getTime();
+    this.effects.invoke('loop', timePos);
+  }
+});
+
+Effect.Queues = {
+  instances: $H(),
+  get: function(queueName) {
+    if(typeof queueName != 'string') return queueName;
+    
+    if(!this.instances[queueName])
+      this.instances[queueName] = new Effect.ScopedQueue();
+      
+    return this.instances[queueName];
+  }
+}
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.DefaultOptions = {
+  transition: Effect.Transitions.sinoidal,
+  duration:   1.0,   // seconds
+  fps:        25.0,  // max. 25fps due to Effect.Queue implementation
+  sync:       false, // true for combining
+  from:       0.0,
+  to:         1.0,
+  delay:      0.0,
+  queue:      'parallel'
+}
+
+Effect.Base = function() {};
+Effect.Base.prototype = {
+  position: null,
+  start: function(options) {
+    this.options      = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
+    this.currentFrame = 0;
+    this.state        = 'idle';
+    this.startOn      = this.options.delay*1000;
+    this.finishOn     = this.startOn + (this.options.duration*1000);
+    this.event('beforeStart');
+    if(!this.options.sync)
+      Effect.Queues.get(typeof this.options.queue == 'string' ? 
+        'global' : this.options.queue.scope).add(this);
+  },
+  loop: function(timePos) {
+    if(timePos >= this.startOn) {
+      if(timePos >= this.finishOn) {
+        this.render(1.0);
+        this.cancel();
+        this.event('beforeFinish');
+        if(this.finish) this.finish(); 
+        this.event('afterFinish');
+        return;  
+      }
+      var pos   = (timePos - this.startOn) / (this.finishOn - this.startOn);
+      var frame = Math.round(pos * this.options.fps * this.options.duration);
+      if(frame > this.currentFrame) {
+        this.render(pos);
+        this.currentFrame = frame;
+      }
+    }
+  },
+  render: function(pos) {
+    if(this.state == 'idle') {
+      this.state = 'running';
+      this.event('beforeSetup');
+      if(this.setup) this.setup();
+      this.event('afterSetup');
+    }
+    if(this.state == 'running') {
+      if(this.options.transition) pos = this.options.transition(pos);
+      pos *= (this.options.to-this.options.from);
+      pos += this.options.from;
+      this.position = pos;
+      this.event('beforeUpdate');
+      if(this.update) this.update(pos);
+      this.event('afterUpdate');
+    }
+  },
+  cancel: function() {
+    if(!this.options.sync)
+      Effect.Queues.get(typeof this.options.queue == 'string' ? 
+        'global' : this.options.queue.scope).remove(this);
+    this.state = 'finished';
+  },
+  event: function(eventName) {
+    if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+    if(this.options[eventName]) this.options[eventName](this);
+  },
+  inspect: function() {
+    return '#<Effect:' + $H(this).inspect() + ',options:' + $H(this.options).inspect() + '>';
+  }
+}
+
+Effect.Parallel = Class.create();
+Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
+  initialize: function(effects) {
+    this.effects = effects || [];
+    this.start(arguments[1]);
+  },
+  update: function(position) {
+    this.effects.invoke('render', position);
+  },
+  finish: function(position) {
+    this.effects.each( function(effect) {
+      effect.render(1.0);
+      effect.cancel();
+      effect.event('beforeFinish');
+      if(effect.finish) effect.finish(position);
+      effect.event('afterFinish');
+    });
+  }
+});
+
+Effect.Opacity = Class.create();
+Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
+  initialize: function(element) {
+    this.element = $(element);
+    // make this work on IE on elements without 'layout'
+    if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout))
+      this.element.setStyle({zoom: 1});
+    var options = Object.extend({
+      from: this.element.getOpacity() || 0.0,
+      to:   1.0
+    }, arguments[1] || {});
+    this.start(options);
+  },
+  update: function(position) {
+    this.element.setOpacity(position);
+  }
+});
+
+Effect.Move = Class.create();
+Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
+  initialize: function(element) {
+    this.element = $(element);
+    var options = Object.extend({
+      x:    0,
+      y:    0,
+      mode: 'relative'
+    }, arguments[1] || {});
+    this.start(options);
+  },
+  setup: function() {
+    // Bug in Opera: Opera returns the "real" position of a static element or
+    // relative element that does not have top/left explicitly set.
+    // ==> Always set top and left for position relative elements in your stylesheets 
+    // (to 0 if you do not need them) 
+    this.element.makePositioned();
+    this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+    this.originalTop  = parseFloat(this.element.getStyle('top')  || '0');
+    if(this.options.mode == 'absolute') {
+      // absolute movement, so we need to calc deltaX and deltaY
+      this.options.x = this.options.x - this.originalLeft;
+      this.options.y = this.options.y - this.originalTop;
+    }
+  },
+  update: function(position) {
+    this.element.setStyle({
+      left: this.options.x  * position + this.originalLeft + 'px',
+      top:  this.options.y  * position + this.originalTop  + 'px'
+    });
+  }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+  return new Effect.Move(element, 
+    Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
+};
+
+Effect.Scale = Class.create();
+Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
+  initialize: function(element, percent) {
+    this.element = $(element)
+    var options = Object.extend({
+      scaleX: true,
+      scaleY: true,
+      scaleContent: true,
+      scaleFromCenter: false,
+      scaleMode: 'box',        // 'box' or 'contents' or {} with provided values
+      scaleFrom: 100.0,
+      scaleTo:   percent
+    }, arguments[2] || {});
+    this.start(options);
+  },
+  setup: function() {
+    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+    this.elementPositioning = this.element.getStyle('position');
+    
+    this.originalStyle = {};
+    ['top','left','width','height','fontSize'].each( function(k) {
+      this.originalStyle[k] = this.element.style[k];
+    }.bind(this));
+      
+    this.originalTop  = this.element.offsetTop;
+    this.originalLeft = this.element.offsetLeft;
+    
+    var fontSize = this.element.getStyle('font-size') || '100%';
+    ['em','px','%'].each( function(fontSizeType) {
+      if(fontSize.indexOf(fontSizeType)>0) {
+        this.fontSize     = parseFloat(fontSize);
+        this.fontSizeType = fontSizeType;
+      }
+    }.bind(this));
+    
+    this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+    
+    this.dims = null;
+    if(this.options.scaleMode=='box')
+      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+    if(/^content/.test(this.options.scaleMode))
+      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+    if(!this.dims)
+      this.dims = [this.options.scaleMode.originalHeight,
+                   this.options.scaleMode.originalWidth];
+  },
+  update: function(position) {
+    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+    if(this.options.scaleContent && this.fontSize)
+      this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+  },
+  finish: function(position) {
+    if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+  },
+  setDimensions: function(height, width) {
+    var d = {};
+    if(this.options.scaleX) d.width = width + 'px';
+    if(this.options.scaleY) d.height = height + 'px';
+    if(this.options.scaleFromCenter) {
+      var topd  = (height - this.dims[0])/2;
+      var leftd = (width  - this.dims[1])/2;
+      if(this.elementPositioning == 'absolute') {
+        if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
+        if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+      } else {
+        if(this.options.scaleY) d.top = -topd + 'px';
+        if(this.options.scaleX) d.left = -leftd + 'px';
+      }
+    }
+    this.element.setStyle(d);
+  }
+});
+
+Effect.Highlight = Class.create();
+Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
+  initialize: function(element) {
+    this.element = $(element);
+    var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
+    this.start(options);
+  },
+  setup: function() {
+    // Prevent executing on elements not in the layout flow
+    if(this.element.getStyle('display')=='none') { this.cancel(); return; }
+    // Disable background image during the effect
+    this.oldStyle = {
+      backgroundImage: this.element.getStyle('background-image') };
+    this.element.setStyle({backgroundImage: 'none'});
+    if(!this.options.endcolor)
+      this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+    if(!this.options.restorecolor)
+      this.options.restorecolor = this.element.getStyle('background-color');
+    // init color calculations
+    this._base  = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+    this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+  },
+  update: function(position) {
+    this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+      return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
+  },
+  finish: function() {
+    this.element.setStyle(Object.extend(this.oldStyle, {
+      backgroundColor: this.options.restorecolor
+    }));
+  }
+});
+
+Effect.ScrollTo = Class.create();
+Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
+  initialize: function(element) {
+    this.element = $(element);
+    this.start(arguments[1] || {});
+  },
+  setup: function() {
+    Position.prepare();
+    var offsets = Position.cumulativeOffset(this.element);
+    if(this.options.offset) offsets[1] += this.options.offset;
+    var max = window.innerHeight ? 
+      window.height - window.innerHeight :
+      document.body.scrollHeight - 
+        (document.documentElement.clientHeight ? 
+          document.documentElement.clientHeight : document.body.clientHeight);
+    this.scrollStart = Position.deltaY;
+    this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
+  },
+  update: function(position) {
+    Position.prepare();
+    window.scrollTo(Position.deltaX, 
+      this.scrollStart + (position*this.delta));
+  }
+});
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+  element = $(element);
+  var oldOpacity = element.getInlineOpacity();
+  var options = Object.extend({
+  from: element.getOpacity() || 1.0,
+  to:   0.0,
+  afterFinishInternal: function(effect) { 
+    if(effect.options.to!=0) return;
+    effect.element.hide();
+    effect.element.setStyle({opacity: oldOpacity}); 
+  }}, arguments[1] || {});
+  return new Effect.Opacity(element,options);
+}
+
+Effect.Appear = function(element) {
+  element = $(element);
+  var options = Object.extend({
+  from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+  to:   1.0,
+  // force Safari to render floated elements properly
+  afterFinishInternal: function(effect) {
+    effect.element.forceRerendering();
+  },
+  beforeSetup: function(effect) {
+    effect.element.setOpacity(effect.options.from);
+    effect.element.show(); 
+  }}, arguments[1] || {});
+  return new Effect.Opacity(element,options);
+}
+
+Effect.Puff = function(element) {
+  element = $(element);
+  var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position') };
+  return new Effect.Parallel(
+   [ new Effect.Scale(element, 200, 
+      { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), 
+     new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], 
+     Object.extend({ duration: 1.0, 
+      beforeSetupInternal: function(effect) {
+        effect.effects[0].element.setStyle({position: 'absolute'}); },
+      afterFinishInternal: function(effect) {
+         effect.effects[0].element.hide();
+         effect.effects[0].element.setStyle(oldStyle); }
+     }, arguments[1] || {})
+   );
+}
+
+Effect.BlindUp = function(element) {
+  element = $(element);
+  element.makeClipping();
+  return new Effect.Scale(element, 0, 
+    Object.extend({ scaleContent: false, 
+      scaleX: false, 
+      restoreAfterFinish: true,
+      afterFinishInternal: function(effect) {
+        effect.element.hide();
+        effect.element.undoClipping();
+      } 
+    }, arguments[1] || {})
+  );
+}
+
+Effect.BlindDown = function(element) {
+  element = $(element);
+  var elementDimensions = element.getDimensions();
+  return new Effect.Scale(element, 100, 
+    Object.extend({ scaleContent: false, 
+      scaleX: false,
+      scaleFrom: 0,
+      scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+      restoreAfterFinish: true,
+      afterSetup: function(effect) {
+        effect.element.makeClipping();
+        effect.element.setStyle({height: '0px'});
+        effect.element.show(); 
+      },  
+      afterFinishInternal: function(effect) {
+        effect.element.undoClipping();
+      }
+    }, arguments[1] || {})
+  );
+}
+
+Effect.SwitchOff = function(element) {
+  element = $(element);
+  var oldOpacity = element.getInlineOpacity();
+  return new Effect.Appear(element, { 
+    duration: 0.4,
+    from: 0,
+    transition: Effect.Transitions.flicker,
+    afterFinishInternal: function(effect) {
+      new Effect.Scale(effect.element, 1, { 
+        duration: 0.3, scaleFromCenter: true,
+        scaleX: false, scaleContent: false, restoreAfterFinish: true,
+        beforeSetup: function(effect) { 
+          effect.element.makePositioned();
+          effect.element.makeClipping();
+        },
+        afterFinishInternal: function(effect) {
+          effect.element.hide();
+          effect.element.undoClipping();
+          effect.element.undoPositioned();
+          effect.element.setStyle({opacity: oldOpacity});
+        }
+      })
+    }
+  });
+}
+
+Effect.DropOut = function(element) {
+  element = $(element);
+  var oldStyle = {
+    top: element.getStyle('top'),
+    left: element.getStyle('left'),
+    opacity: element.getInlineOpacity() };
+  return new Effect.Parallel(
+    [ new Effect.Move(element, {x: 0, y: 100, sync: true }), 
+      new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+    Object.extend(
+      { duration: 0.5,
+        beforeSetup: function(effect) {
+          effect.effects[0].element.makePositioned(); 
+        },
+        afterFinishInternal: function(effect) {
+          effect.effects[0].element.hide();
+          effect.effects[0].element.undoPositioned();
+          effect.effects[0].element.setStyle(oldStyle);
+        } 
+      }, arguments[1] || {}));
+}
+
+Effect.Shake = function(element) {
+  element = $(element);
+  var oldStyle = {
+    top: element.getStyle('top'),
+    left: element.getStyle('left') };
+    return new Effect.Move(element, 
+      { x:  20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
+        effect.element.undoPositioned();
+        effect.element.setStyle(oldStyle);
+  }}) }}) }}) }}) }}) }});
+}
+
+Effect.SlideDown = function(element) {
+  element = $(element);
+  element.cleanWhitespace();
+  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+  var oldInnerBottom = $(element.firstChild).getStyle('bottom');
+  var elementDimensions = element.getDimensions();
+  return new Effect.Scale(element, 100, Object.extend({ 
+    scaleContent: false, 
+    scaleX: false, 
+    scaleFrom: window.opera ? 0 : 1,
+    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+    restoreAfterFinish: true,
+    afterSetup: function(effect) {
+      effect.element.makePositioned();
+      effect.element.firstChild.makePositioned();
+      if(window.opera) effect.element.setStyle({top: ''});
+      effect.element.makeClipping();
+      effect.element.setStyle({height: '0px'});
+      effect.element.show(); },
+    afterUpdateInternal: function(effect) {
+      effect.element.firstChild.setStyle({bottom:
+        (effect.dims[0] - effect.element.clientHeight) + 'px' }); 
+    },
+    afterFinishInternal: function(effect) {
+      effect.element.undoClipping(); 
+      // IE will crash if child is undoPositioned first
+      if(/MSIE/.test(navigator.userAgent)){
+        effect.element.undoPositioned();
+        effect.element.firstChild.undoPositioned();
+      }else{
+        effect.element.firstChild.undoPositioned();
+        effect.element.undoPositioned();
+      }
+      effect.element.firstChild.setStyle({bottom: oldInnerBottom}); }
+    }, arguments[1] || {})
+  );
+}
+  
+Effect.SlideUp = function(element) {
+  element = $(element);
+  element.cleanWhitespace();
+  var oldInnerBottom = $(element.firstChild).getStyle('bottom');
+  return new Effect.Scale(element, window.opera ? 0 : 1,
+   Object.extend({ scaleContent: false, 
+    scaleX: false, 
+    scaleMode: 'box',
+    scaleFrom: 100,
+    restoreAfterFinish: true,
+    beforeStartInternal: function(effect) {
+      effect.element.makePositioned();
+      effect.element.firstChild.makePositioned();
+      if(window.opera) effect.element.setStyle({top: ''});
+      effect.element.makeClipping();
+      effect.element.show(); },  
+    afterUpdateInternal: function(effect) {
+      effect.element.firstChild.setStyle({bottom:
+        (effect.dims[0] - effect.element.clientHeight) + 'px' }); },
+    afterFinishInternal: function(effect) {
+      effect.element.hide();
+      effect.element.undoClipping();
+      effect.element.firstChild.undoPositioned();
+      effect.element.undoPositioned();
+      effect.element.setStyle({bottom: oldInnerBottom}); }
+   }, arguments[1] || {})
+  );
+}
+
+// Bug in opera makes the TD containing this element expand for a instance after finish 
+Effect.Squish = function(element) {
+  return new Effect.Scale(element, window.opera ? 1 : 0, 
+    { restoreAfterFinish: true,
+      beforeSetup: function(effect) {
+        effect.element.makeClipping(effect.element); },  
+      afterFinishInternal: function(effect) {
+        effect.element.hide(effect.element); 
+        effect.element.undoClipping(effect.element); }
+  });
+}
+
+Effect.Grow = function(element) {
+  element = $(element);
+  var options = Object.extend({
+    direction: 'center',
+    moveTransition: Effect.Transitions.sinoidal,
+    scaleTransition: Effect.Transitions.sinoidal,
+    opacityTransition: Effect.Transitions.full
+  }, arguments[1] || {});
+  var oldStyle = {
+    top: element.style.top,
+    left: element.style.left,
+    height: element.style.height,
+    width: element.style.width,
+    opacity: element.getInlineOpacity() };
+
+  var dims = element.getDimensions();    
+  var initialMoveX, initialMoveY;
+  var moveX, moveY;
+  
+  switch (options.direction) {
+    case 'top-left':
+      initialMoveX = initialMoveY = moveX = moveY = 0; 
+      break;
+    case 'top-right':
+      initialMoveX = dims.width;
+      initialMoveY = moveY = 0;
+      moveX = -dims.width;
+      break;
+    case 'bottom-left':
+      initialMoveX = moveX = 0;
+      initialMoveY = dims.height;
+      moveY = -dims.height;
+      break;
+    case 'bottom-right':
+      initialMoveX = dims.width;
+      initialMoveY = dims.height;
+      moveX = -dims.width;
+      moveY = -dims.height;
+      break;
+    case 'center':
+      initialMoveX = dims.width / 2;
+      initialMoveY = dims.height / 2;
+      moveX = -dims.width / 2;
+      moveY = -dims.height / 2;
+      break;
+  }
+  
+  return new Effect.Move(element, {
+    x: initialMoveX,
+    y: initialMoveY,
+    duration: 0.01, 
+    beforeSetup: function(effect) {
+      effect.element.hide();
+      effect.element.makeClipping();
+      effect.element.makePositioned();
+    },
+    afterFinishInternal: function(effect) {
+      new Effect.Parallel(
+        [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+          new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+          new Effect.Scale(effect.element, 100, {
+            scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, 
+            sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+        ], Object.extend({
+             beforeSetup: function(effect) {
+               effect.effects[0].element.setStyle({height: '0px'});
+               effect.effects[0].element.show(); 
+             },
+             afterFinishInternal: function(effect) {
+               effect.effects[0].element.undoClipping();
+               effect.effects[0].element.undoPositioned();
+               effect.effects[0].element.setStyle(oldStyle); 
+             }
+           }, options)
+      )
+    }
+  });
+}
+
+Effect.Shrink = function(element) {
+  element = $(element);
+  var options = Object.extend({
+    direction: 'center',
+    moveTransition: Effect.Transitions.sinoidal,
+    scaleTransition: Effect.Transitions.sinoidal,
+    opacityTransition: Effect.Transitions.none
+  }, arguments[1] || {});
+  var oldStyle = {
+    top: element.style.top,
+    left: element.style.left,
+    height: element.style.height,
+    width: element.style.width,
+    opacity: element.getInlineOpacity() };
+
+  var dims = element.getDimensions();
+  var moveX, moveY;
+  
+  switch (options.direction) {
+    case 'top-left':
+      moveX = moveY = 0;
+      break;
+    case 'top-right':
+      moveX = dims.width;
+      moveY = 0;
+      break;
+    case 'bottom-left':
+      moveX = 0;
+      moveY = dims.height;
+      break;
+    case 'bottom-right':
+      moveX = dims.width;
+      moveY = dims.height;
+      break;
+    case 'center':  
+      moveX = dims.width / 2;
+      moveY = dims.height / 2;
+      break;
+  }
+  
+  return new Effect.Parallel(
+    [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+      new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+      new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+    ], Object.extend({            
+         beforeStartInternal: function(effect) {
+           effect.effects[0].element.makePositioned();
+           effect.effects[0].element.makeClipping(); },
+         afterFinishInternal: function(effect) {
+           effect.effects[0].element.hide();
+           effect.effects[0].element.undoClipping();
+           effect.effects[0].element.undoPositioned();
+           effect.effects[0].element.setStyle(oldStyle); }
+       }, options)
+  );
+}
+
+Effect.Pulsate = function(element) {
+  element = $(element);
+  var options    = arguments[1] || {};
+  var oldOpacity = element.getInlineOpacity();
+  var transition = options.transition || Effect.Transitions.sinoidal;
+  var reverser   = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) };
+  reverser.bind(transition);
+  return new Effect.Opacity(element, 
+    Object.extend(Object.extend({  duration: 3.0, from: 0,
+      afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+    }, options), {transition: reverser}));
+}
+
+Effect.Fold = function(element) {
+  element = $(element);
+  var oldStyle = {
+    top: element.style.top,
+    left: element.style.left,
+    width: element.style.width,
+    height: element.style.height };
+  Element.makeClipping(element);
+  return new Effect.Scale(element, 5, Object.extend({   
+    scaleContent: false,
+    scaleX: false,
+    afterFinishInternal: function(effect) {
+    new Effect.Scale(element, 1, { 
+      scaleContent: false, 
+      scaleY: false,
+      afterFinishInternal: function(effect) {
+        effect.element.hide();
+        effect.element.undoClipping(); 
+        effect.element.setStyle(oldStyle);
+      } });
+  }}, arguments[1] || {}));
+};
+
+['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom',
+ 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each( 
+  function(f) { Element.Methods[f] = Element[f]; }
+);
+
+Element.Methods.visualEffect = function(element, effect, options) {
+  s = effect.gsub(/_/, '-').camelize();
+  effect_class = s.charAt(0).toUpperCase() + s.substring(1);
+  new Effect[effect_class](element, options);
+  return $(element);
+};
+
+Element.addMethods();
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/prototype.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/prototype.js
new file mode 100644 (file)
index 0000000..0caf9cd
--- /dev/null
@@ -0,0 +1,2006 @@
+/*  Prototype JavaScript framework, version 1.5.0_rc0
+ *  (c) 2005 Sam Stephenson <sam@conio.net>
+ *
+ *  Prototype is freely distributable under the terms of an MIT-style license.
+ *  For details, see the Prototype web site: http://prototype.conio.net/
+ *
+/*--------------------------------------------------------------------------*/
+
+var Prototype = {
+  Version: '1.5.0_rc0',
+  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
+
+  emptyFunction: function() {},
+  K: function(x) {return x}
+}
+
+var Class = {
+  create: function() {
+    return function() {
+      this.initialize.apply(this, arguments);
+    }
+  }
+}
+
+var Abstract = new Object();
+
+Object.extend = function(destination, source) {
+  for (var property in source) {
+    destination[property] = source[property];
+  }
+  return destination;
+}
+
+Object.inspect = function(object) {
+  try {
+    if (object == undefined) return 'undefined';
+    if (object == null) return 'null';
+    return object.inspect ? object.inspect() : object.toString();
+  } catch (e) {
+    if (e instanceof RangeError) return '...';
+    throw e;
+  }
+}
+
+Function.prototype.bind = function() {
+  var __method = this, args = $A(arguments), object = args.shift();
+  return function() {
+    return __method.apply(object, args.concat($A(arguments)));
+  }
+}
+
+Function.prototype.bindAsEventListener = function(object) {
+  var __method = this;
+  return function(event) {
+    return __method.call(object, event || window.event);
+  }
+}
+
+Object.extend(Number.prototype, {
+  toColorPart: function() {
+    var digits = this.toString(16);
+    if (this < 16) return '0' + digits;
+    return digits;
+  },
+
+  succ: function() {
+    return this + 1;
+  },
+
+  times: function(iterator) {
+    $R(0, this, true).each(iterator);
+    return this;
+  }
+});
+
+var Try = {
+  these: function() {
+    var returnValue;
+
+    for (var i = 0; i < arguments.length; i++) {
+      var lambda = arguments[i];
+      try {
+        returnValue = lambda();
+        break;
+      } catch (e) {}
+    }
+
+    return returnValue;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create();
+PeriodicalExecuter.prototype = {
+  initialize: function(callback, frequency) {
+    this.callback = callback;
+    this.frequency = frequency;
+    this.currentlyExecuting = false;
+
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    if (!this.currentlyExecuting) {
+      try {
+        this.currentlyExecuting = true;
+        this.callback();
+      } finally {
+        this.currentlyExecuting = false;
+      }
+    }
+  }
+}
+Object.extend(String.prototype, {
+  gsub: function(pattern, replacement) {
+    var result = '', source = this, match;
+    replacement = arguments.callee.prepareReplacement(replacement);
+
+    while (source.length > 0) {
+      if (match = source.match(pattern)) {
+        result += source.slice(0, match.index);
+        result += (replacement(match) || '').toString();
+        source  = source.slice(match.index + match[0].length);
+      } else {
+        result += source, source = '';
+      }
+    }
+    return result;
+  },
+
+  sub: function(pattern, replacement, count) {
+    replacement = this.gsub.prepareReplacement(replacement);
+    count = count === undefined ? 1 : count;
+
+    return this.gsub(pattern, function(match) {
+      if (--count < 0) return match[0];
+      return replacement(match);
+    });
+  },
+
+  scan: function(pattern, iterator) {
+    this.gsub(pattern, iterator);
+    return this;
+  },
+
+  truncate: function(length, truncation) {
+    length = length || 30;
+    truncation = truncation === undefined ? '...' : truncation;
+    return this.length > length ?
+      this.slice(0, length - truncation.length) + truncation : this;
+  },
+
+  strip: function() {
+    return this.replace(/^\s+/, '').replace(/\s+$/, '');
+  },
+
+  stripTags: function() {
+    return this.replace(/<\/?[^>]+>/gi, '');
+  },
+
+  stripScripts: function() {
+    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+  },
+
+  extractScripts: function() {
+    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+    return (this.match(matchAll) || []).map(function(scriptTag) {
+      return (scriptTag.match(matchOne) || ['', ''])[1];
+    });
+  },
+
+  evalScripts: function() {
+    return this.extractScripts().map(function(script) { return eval(script) });
+  },
+
+  escapeHTML: function() {
+    var div = document.createElement('div');
+    var text = document.createTextNode(this);
+    div.appendChild(text);
+    return div.innerHTML;
+  },
+
+  unescapeHTML: function() {
+    var div = document.createElement('div');
+    div.innerHTML = this.stripTags();
+    return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
+  },
+
+  toQueryParams: function() {
+    var pairs = this.match(/^\??(.*)$/)[1].split('&');
+    return pairs.inject({}, function(params, pairString) {
+      var pair = pairString.split('=');
+      params[pair[0]] = pair[1];
+      return params;
+    });
+  },
+
+  toArray: function() {
+    return this.split('');
+  },
+
+  camelize: function() {
+    var oStringList = this.split('-');
+    if (oStringList.length == 1) return oStringList[0];
+
+    var camelizedString = this.indexOf('-') == 0
+      ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
+      : oStringList[0];
+
+    for (var i = 1, len = oStringList.length; i < len; i++) {
+      var s = oStringList[i];
+      camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
+    }
+
+    return camelizedString;
+  },
+
+  inspect: function() {
+    return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'";
+  }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+  if (typeof replacement == 'function') return replacement;
+  var template = new Template(replacement);
+  return function(match) { return template.evaluate(match) };
+}
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+var Template = Class.create();
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+Template.prototype = {
+  initialize: function(template, pattern) {
+    this.template = template.toString();
+    this.pattern  = pattern || Template.Pattern;
+  },
+
+  evaluate: function(object) {
+    return this.template.gsub(this.pattern, function(match) {
+      var before = match[1];
+      if (before == '\\') return match[2];
+      return before + (object[match[3]] || '').toString();
+    });
+  }
+}
+
+var $break    = new Object();
+var $continue = new Object();
+
+var Enumerable = {
+  each: function(iterator) {
+    var index = 0;
+    try {
+      this._each(function(value) {
+        try {
+          iterator(value, index++);
+        } catch (e) {
+          if (e != $continue) throw e;
+        }
+      });
+    } catch (e) {
+      if (e != $break) throw e;
+    }
+  },
+
+  all: function(iterator) {
+    var result = true;
+    this.each(function(value, index) {
+      result = result && !!(iterator || Prototype.K)(value, index);
+      if (!result) throw $break;
+    });
+    return result;
+  },
+
+  any: function(iterator) {
+    var result = true;
+    this.each(function(value, index) {
+      if (result = !!(iterator || Prototype.K)(value, index))
+        throw $break;
+    });
+    return result;
+  },
+
+  collect: function(iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      results.push(iterator(value, index));
+    });
+    return results;
+  },
+
+  detect: function (iterator) {
+    var result;
+    this.each(function(value, index) {
+      if (iterator(value, index)) {
+        result = value;
+        throw $break;
+      }
+    });
+    return result;
+  },
+
+  findAll: function(iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      if (iterator(value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  grep: function(pattern, iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      var stringValue = value.toString();
+      if (stringValue.match(pattern))
+        results.push((iterator || Prototype.K)(value, index));
+    })
+    return results;
+  },
+
+  include: function(object) {
+    var found = false;
+    this.each(function(value) {
+      if (value == object) {
+        found = true;
+        throw $break;
+      }
+    });
+    return found;
+  },
+
+  inject: function(memo, iterator) {
+    this.each(function(value, index) {
+      memo = iterator(memo, value, index);
+    });
+    return memo;
+  },
+
+  invoke: function(method) {
+    var args = $A(arguments).slice(1);
+    return this.collect(function(value) {
+      return value[method].apply(value, args);
+    });
+  },
+
+  max: function(iterator) {
+    var result;
+    this.each(function(value, index) {
+      value = (iterator || Prototype.K)(value, index);
+      if (result == undefined || value >= result)
+        result = value;
+    });
+    return result;
+  },
+
+  min: function(iterator) {
+    var result;
+    this.each(function(value, index) {
+      value = (iterator || Prototype.K)(value, index);
+      if (result == undefined || value < result)
+        result = value;
+    });
+    return result;
+  },
+
+  partition: function(iterator) {
+    var trues = [], falses = [];
+    this.each(function(value, index) {
+      ((iterator || Prototype.K)(value, index) ?
+        trues : falses).push(value);
+    });
+    return [trues, falses];
+  },
+
+  pluck: function(property) {
+    var results = [];
+    this.each(function(value, index) {
+      results.push(value[property]);
+    });
+    return results;
+  },
+
+  reject: function(iterator) {
+    var results = [];
+    this.each(function(value, index) {
+      if (!iterator(value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  sortBy: function(iterator) {
+    return this.collect(function(value, index) {
+      return {value: value, criteria: iterator(value, index)};
+    }).sort(function(left, right) {
+      var a = left.criteria, b = right.criteria;
+      return a < b ? -1 : a > b ? 1 : 0;
+    }).pluck('value');
+  },
+
+  toArray: function() {
+    return this.collect(Prototype.K);
+  },
+
+  zip: function() {
+    var iterator = Prototype.K, args = $A(arguments);
+    if (typeof args.last() == 'function')
+      iterator = args.pop();
+
+    var collections = [this].concat(args).map($A);
+    return this.map(function(value, index) {
+      return iterator(collections.pluck(index));
+    });
+  },
+
+  inspect: function() {
+    return '#<Enumerable:' + this.toArray().inspect() + '>';
+  }
+}
+
+Object.extend(Enumerable, {
+  map:     Enumerable.collect,
+  find:    Enumerable.detect,
+  select:  Enumerable.findAll,
+  member:  Enumerable.include,
+  entries: Enumerable.toArray
+});
+var $A = Array.from = function(iterable) {
+  if (!iterable) return [];
+  if (iterable.toArray) {
+    return iterable.toArray();
+  } else {
+    var results = [];
+    for (var i = 0; i < iterable.length; i++)
+      results.push(iterable[i]);
+    return results;
+  }
+}
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse)
+  Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+  _each: function(iterator) {
+    for (var i = 0; i < this.length; i++)
+      iterator(this[i]);
+  },
+
+  clear: function() {
+    this.length = 0;
+    return this;
+  },
+
+  first: function() {
+    return this[0];
+  },
+
+  last: function() {
+    return this[this.length - 1];
+  },
+
+  compact: function() {
+    return this.select(function(value) {
+      return value != undefined || value != null;
+    });
+  },
+
+  flatten: function() {
+    return this.inject([], function(array, value) {
+      return array.concat(value && value.constructor == Array ?
+        value.flatten() : [value]);
+    });
+  },
+
+  without: function() {
+    var values = $A(arguments);
+    return this.select(function(value) {
+      return !values.include(value);
+    });
+  },
+
+  indexOf: function(object) {
+    for (var i = 0; i < this.length; i++)
+      if (this[i] == object) return i;
+    return -1;
+  },
+
+  reverse: function(inline) {
+    return (inline !== false ? this : this.toArray())._reverse();
+  },
+
+  inspect: function() {
+    return '[' + this.map(Object.inspect).join(', ') + ']';
+  }
+});
+var Hash = {
+  _each: function(iterator) {
+    for (var key in this) {
+      var value = this[key];
+      if (typeof value == 'function') continue;
+
+      var pair = [key, value];
+      pair.key = key;
+      pair.value = value;
+      iterator(pair);
+    }
+  },
+
+  keys: function() {
+    return this.pluck('key');
+  },
+
+  values: function() {
+    return this.pluck('value');
+  },
+
+  merge: function(hash) {
+    return $H(hash).inject($H(this), function(mergedHash, pair) {
+      mergedHash[pair.key] = pair.value;
+      return mergedHash;
+    });
+  },
+
+  toQueryString: function() {
+    return this.map(function(pair) {
+      return pair.map(encodeURIComponent).join('=');
+    }).join('&');
+  },
+
+  inspect: function() {
+    return '#<Hash:{' + this.map(function(pair) {
+      return pair.map(Object.inspect).join(': ');
+    }).join(', ') + '}>';
+  }
+}
+
+function $H(object) {
+  var hash = Object.extend({}, object || {});
+  Object.extend(hash, Enumerable);
+  Object.extend(hash, Hash);
+  return hash;
+}
+ObjectRange = Class.create();
+Object.extend(ObjectRange.prototype, Enumerable);
+Object.extend(ObjectRange.prototype, {
+  initialize: function(start, end, exclusive) {
+    this.start = start;
+    this.end = end;
+    this.exclusive = exclusive;
+  },
+
+  _each: function(iterator) {
+    var value = this.start;
+    do {
+      iterator(value);
+      value = value.succ();
+    } while (this.include(value));
+  },
+
+  include: function(value) {
+    if (value < this.start)
+      return false;
+    if (this.exclusive)
+      return value < this.end;
+    return value <= this.end;
+  }
+});
+
+var $R = function(start, end, exclusive) {
+  return new ObjectRange(start, end, exclusive);
+}
+
+var Ajax = {
+  getTransport: function() {
+    return Try.these(
+      function() {return new XMLHttpRequest()},
+      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+    ) || false;
+  },
+
+  activeRequestCount: 0
+}
+
+Ajax.Responders = {
+  responders: [],
+
+  _each: function(iterator) {
+    this.responders._each(iterator);
+  },
+
+  register: function(responderToAdd) {
+    if (!this.include(responderToAdd))
+      this.responders.push(responderToAdd);
+  },
+
+  unregister: function(responderToRemove) {
+    this.responders = this.responders.without(responderToRemove);
+  },
+
+  dispatch: function(callback, request, transport, json) {
+    this.each(function(responder) {
+      if (responder[callback] && typeof responder[callback] == 'function') {
+        try {
+          responder[callback].apply(responder, [request, transport, json]);
+        } catch (e) {}
+      }
+    });
+  }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+  onCreate: function() {
+    Ajax.activeRequestCount++;
+  },
+
+  onComplete: function() {
+    Ajax.activeRequestCount--;
+  }
+});
+
+Ajax.Base = function() {};
+Ajax.Base.prototype = {
+  setOptions: function(options) {
+    this.options = {
+      method:       'post',
+      asynchronous: true,
+      contentType:  'application/x-www-form-urlencoded',
+      parameters:   ''
+    }
+    Object.extend(this.options, options || {});
+  },
+
+  responseIsSuccess: function() {
+    return this.transport.status == undefined
+        || this.transport.status == 0
+        || (this.transport.status >= 200 && this.transport.status < 300);
+  },
+
+  responseIsFailure: function() {
+    return !this.responseIsSuccess();
+  }
+}
+
+Ajax.Request = Class.create();
+Ajax.Request.Events =
+  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
+  initialize: function(url, options) {
+    this.transport = Ajax.getTransport();
+    this.setOptions(options);
+    this.request(url);
+  },
+
+  request: function(url) {
+    var parameters = this.options.parameters || '';
+    if (parameters.length > 0) parameters += '&_=';
+
+    try {
+      this.url = url;
+      if (this.options.method == 'get' && parameters.length > 0)
+        this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
+
+      Ajax.Responders.dispatch('onCreate', this, this.transport);
+
+      this.transport.open(this.options.method, this.url,
+        this.options.asynchronous);
+
+      if (this.options.asynchronous) {
+        this.transport.onreadystatechange = this.onStateChange.bind(this);
+        setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
+      }
+
+      this.setRequestHeaders();
+
+      var body = this.options.postBody ? this.options.postBody : parameters;
+      this.transport.send(this.options.method == 'post' ? body : null);
+
+    } catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  setRequestHeaders: function() {
+    var requestHeaders =
+      ['X-Requested-With', 'XMLHttpRequest',
+       'X-Prototype-Version', Prototype.Version,
+       'Accept', 'text/javascript, text/html, application/xml, text/xml, */*'];
+
+    if (this.options.method == 'post') {
+      requestHeaders.push('Content-type', this.options.contentType);
+
+      /* Force "Connection: close" for Mozilla browsers to work around
+       * a bug where XMLHttpReqeuest sends an incorrect Content-length
+       * header. See Mozilla Bugzilla #246651.
+       */
+      if (this.transport.overrideMimeType)
+        requestHeaders.push('Connection', 'close');
+    }
+
+    if (this.options.requestHeaders)
+      requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
+
+    for (var i = 0; i < requestHeaders.length; i += 2)
+      this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
+  },
+
+  onStateChange: function() {
+    var readyState = this.transport.readyState;
+    if (readyState != 1)
+      this.respondToReadyState(this.transport.readyState);
+  },
+
+  header: function(name) {
+    try {
+      return this.transport.getResponseHeader(name);
+    } catch (e) {}
+  },
+
+  evalJSON: function() {
+    try {
+      return eval('(' + this.header('X-JSON') + ')');
+    } catch (e) {}
+  },
+
+  evalResponse: function() {
+    try {
+      return eval(this.transport.responseText);
+    } catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  respondToReadyState: function(readyState) {
+    var event = Ajax.Request.Events[readyState];
+    var transport = this.transport, json = this.evalJSON();
+
+    if (event == 'Complete') {
+      try {
+        (this.options['on' + this.transport.status]
+         || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
+         || Prototype.emptyFunction)(transport, json);
+      } catch (e) {
+        this.dispatchException(e);
+      }
+
+      if ((this.header('Content-type') || '').match(/^text\/javascript/i))
+        this.evalResponse();
+    }
+
+    try {
+      (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
+      Ajax.Responders.dispatch('on' + event, this, transport, json);
+    } catch (e) {
+      this.dispatchException(e);
+    }
+
+    /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
+    if (event == 'Complete')
+      this.transport.onreadystatechange = Prototype.emptyFunction;
+  },
+
+  dispatchException: function(exception) {
+    (this.options.onException || Prototype.emptyFunction)(this, exception);
+    Ajax.Responders.dispatch('onException', this, exception);
+  }
+});
+
+Ajax.Updater = Class.create();
+
+Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
+  initialize: function(container, url, options) {
+    this.containers = {
+      success: container.success ? $(container.success) : $(container),
+      failure: container.failure ? $(container.failure) :
+        (container.success ? null : $(container))
+    }
+
+    this.transport = Ajax.getTransport();
+    this.setOptions(options);
+
+    var onComplete = this.options.onComplete || Prototype.emptyFunction;
+    this.options.onComplete = (function(transport, object) {
+      this.updateContent();
+      onComplete(transport, object);
+    }).bind(this);
+
+    this.request(url);
+  },
+
+  updateContent: function() {
+    var receiver = this.responseIsSuccess() ?
+      this.containers.success : this.containers.failure;
+    var response = this.transport.responseText;
+
+    if (!this.options.evalScripts)
+      response = response.stripScripts();
+
+    if (receiver) {
+      if (this.options.insertion) {
+        new this.options.insertion(receiver, response);
+      } else {
+        Element.update(receiver, response);
+      }
+    }
+
+    if (this.responseIsSuccess()) {
+      if (this.onComplete)
+        setTimeout(this.onComplete.bind(this), 10);
+    }
+  }
+});
+
+Ajax.PeriodicalUpdater = Class.create();
+Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
+  initialize: function(container, url, options) {
+    this.setOptions(options);
+    this.onComplete = this.options.onComplete;
+
+    this.frequency = (this.options.frequency || 2);
+    this.decay = (this.options.decay || 1);
+
+    this.updater = {};
+    this.container = container;
+    this.url = url;
+
+    this.start();
+  },
+
+  start: function() {
+    this.options.onComplete = this.updateComplete.bind(this);
+    this.onTimerEvent();
+  },
+
+  stop: function() {
+    this.updater.onComplete = undefined;
+    clearTimeout(this.timer);
+    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+  },
+
+  updateComplete: function(request) {
+    if (this.options.decay) {
+      this.decay = (request.responseText == this.lastText ?
+        this.decay * this.options.decay : 1);
+
+      this.lastText = request.responseText;
+    }
+    this.timer = setTimeout(this.onTimerEvent.bind(this),
+      this.decay * this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    this.updater = new Ajax.Updater(this.container, this.url, this.options);
+  }
+});
+function $() {
+  var results = [], element;
+  for (var i = 0; i < arguments.length; i++) {
+    element = arguments[i];
+    if (typeof element == 'string')
+      element = document.getElementById(element);
+    results.push(Element.extend(element));
+  }
+  return results.length < 2 ? results[0] : results;
+}
+
+document.getElementsByClassName = function(className, parentElement) {
+  var children = ($(parentElement) || document.body).getElementsByTagName('*');
+  return $A(children).inject([], function(elements, child) {
+    if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
+      elements.push(Element.extend(child));
+    return elements;
+  });
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Element)
+  var Element = new Object();
+
+Element.extend = function(element) {
+  if (!element) return;
+  if (_nativeExtensions) return element;
+
+  if (!element._extended && element.tagName && element != window) {
+    var methods = Element.Methods, cache = Element.extend.cache;
+    for (property in methods) {
+      var value = methods[property];
+      if (typeof value == 'function')
+        element[property] = cache.findOrStore(value);
+    }
+  }
+
+  element._extended = true;
+  return element;
+}
+
+Element.extend.cache = {
+  findOrStore: function(value) {
+    return this[value] = this[value] || function() {
+      return value.apply(null, [this].concat($A(arguments)));
+    }
+  }
+}
+
+Element.Methods = {
+  visible: function(element) {
+    return $(element).style.display != 'none';
+  },
+
+  toggle: function() {
+    for (var i = 0; i < arguments.length; i++) {
+      var element = $(arguments[i]);
+      Element[Element.visible(element) ? 'hide' : 'show'](element);
+    }
+  },
+
+  hide: function() {
+    for (var i = 0; i < arguments.length; i++) {
+      var element = $(arguments[i]);
+      element.style.display = 'none';
+    }
+  },
+
+  show: function() {
+    for (var i = 0; i < arguments.length; i++) {
+      var element = $(arguments[i]);
+      element.style.display = '';
+    }
+  },
+
+  remove: function(element) {
+    element = $(element);
+    element.parentNode.removeChild(element);
+  },
+
+  update: function(element, html) {
+    $(element).innerHTML = html.stripScripts();
+    setTimeout(function() {html.evalScripts()}, 10);
+  },
+
+  replace: function(element, html) {
+    element = $(element);
+    if (element.outerHTML) {
+      element.outerHTML = html.stripScripts();
+    } else {
+      var range = element.ownerDocument.createRange();
+      range.selectNodeContents(element);
+      element.parentNode.replaceChild(
+        range.createContextualFragment(html.stripScripts()), element);
+    }
+    setTimeout(function() {html.evalScripts()}, 10);
+  },
+
+  getHeight: function(element) {
+    element = $(element);
+    return element.offsetHeight;
+  },
+
+  classNames: function(element) {
+    return new Element.ClassNames(element);
+  },
+
+  hasClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    return Element.classNames(element).include(className);
+  },
+
+  addClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    return Element.classNames(element).add(className);
+  },
+
+  removeClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    return Element.classNames(element).remove(className);
+  },
+
+  // removes whitespace-only text node children
+  cleanWhitespace: function(element) {
+    element = $(element);
+    for (var i = 0; i < element.childNodes.length; i++) {
+      var node = element.childNodes[i];
+      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+        Element.remove(node);
+    }
+  },
+
+  empty: function(element) {
+    return $(element).innerHTML.match(/^\s*$/);
+  },
+
+  childOf: function(element, ancestor) {
+    element = $(element), ancestor = $(ancestor);
+    while (element = element.parentNode)
+      if (element == ancestor) return true;
+    return false;
+  },
+
+  scrollTo: function(element) {
+    element = $(element);
+    var x = element.x ? element.x : element.offsetLeft,
+        y = element.y ? element.y : element.offsetTop;
+    window.scrollTo(x, y);
+  },
+
+  getStyle: function(element, style) {
+    element = $(element);
+    var value = element.style[style.camelize()];
+    if (!value) {
+      if (document.defaultView && document.defaultView.getComputedStyle) {
+        var css = document.defaultView.getComputedStyle(element, null);
+        value = css ? css.getPropertyValue(style) : null;
+      } else if (element.currentStyle) {
+        value = element.currentStyle[style.camelize()];
+      }
+    }
+
+    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
+      if (Element.getStyle(element, 'position') == 'static') value = 'auto';
+
+    return value == 'auto' ? null : value;
+  },
+
+  setStyle: function(element, style) {
+    element = $(element);
+    for (var name in style)
+      element.style[name.camelize()] = style[name];
+  },
+
+  getDimensions: function(element) {
+    element = $(element);
+    if (Element.getStyle(element, 'display') != 'none')
+      return {width: element.offsetWidth, height: element.offsetHeight};
+
+    // All *Width and *Height properties give 0 on elements with display none,
+    // so enable the element temporarily
+    var els = element.style;
+    var originalVisibility = els.visibility;
+    var originalPosition = els.position;
+    els.visibility = 'hidden';
+    els.position = 'absolute';
+    els.display = '';
+    var originalWidth = element.clientWidth;
+    var originalHeight = element.clientHeight;
+    els.display = 'none';
+    els.position = originalPosition;
+    els.visibility = originalVisibility;
+    return {width: originalWidth, height: originalHeight};
+  },
+
+  makePositioned: function(element) {
+    element = $(element);
+    var pos = Element.getStyle(element, 'position');
+    if (pos == 'static' || !pos) {
+      element._madePositioned = true;
+      element.style.position = 'relative';
+      // Opera returns the offset relative to the positioning context, when an
+      // element is position relative but top and left have not been defined
+      if (window.opera) {
+        element.style.top = 0;
+        element.style.left = 0;
+      }
+    }
+  },
+
+  undoPositioned: function(element) {
+    element = $(element);
+    if (element._madePositioned) {
+      element._madePositioned = undefined;
+      element.style.position =
+        element.style.top =
+        element.style.left =
+        element.style.bottom =
+        element.style.right = '';
+    }
+  },
+
+  makeClipping: function(element) {
+    element = $(element);
+    if (element._overflow) return;
+    element._overflow = element.style.overflow;
+    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
+      element.style.overflow = 'hidden';
+  },
+
+  undoClipping: function(element) {
+    element = $(element);
+    if (element._overflow) return;
+    element.style.overflow = element._overflow;
+    element._overflow = undefined;
+  }
+}
+
+Object.extend(Element, Element.Methods);
+
+var _nativeExtensions = false;
+
+if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
+  var HTMLElement = {}
+  HTMLElement.prototype = document.createElement('div').__proto__;
+}
+
+Element.addMethods = function(methods) {
+  Object.extend(Element.Methods, methods || {});
+
+  if(typeof HTMLElement != 'undefined') {
+    var methods = Element.Methods, cache = Element.extend.cache;
+    for (property in methods) {
+      var value = methods[property];
+      if (typeof value == 'function')
+        HTMLElement.prototype[property] = cache.findOrStore(value);
+    }
+    _nativeExtensions = true;
+  }
+}
+
+Element.addMethods();
+
+var Toggle = new Object();
+Toggle.display = Element.toggle;
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.Insertion = function(adjacency) {
+  this.adjacency = adjacency;
+}
+
+Abstract.Insertion.prototype = {
+  initialize: function(element, content) {
+    this.element = $(element);
+    this.content = content.stripScripts();
+
+    if (this.adjacency && this.element.insertAdjacentHTML) {
+      try {
+        this.element.insertAdjacentHTML(this.adjacency, this.content);
+      } catch (e) {
+        var tagName = this.element.tagName.toLowerCase();
+        if (tagName == 'tbody' || tagName == 'tr') {
+          this.insertContent(this.contentFromAnonymousTable());
+        } else {
+          throw e;
+        }
+      }
+    } else {
+      this.range = this.element.ownerDocument.createRange();
+      if (this.initializeRange) this.initializeRange();
+      this.insertContent([this.range.createContextualFragment(this.content)]);
+    }
+
+    setTimeout(function() {content.evalScripts()}, 10);
+  },
+
+  contentFromAnonymousTable: function() {
+    var div = document.createElement('div');
+    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
+    return $A(div.childNodes[0].childNodes[0].childNodes);
+  }
+}
+
+var Insertion = new Object();
+
+Insertion.Before = Class.create();
+Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
+  initializeRange: function() {
+    this.range.setStartBefore(this.element);
+  },
+
+  insertContent: function(fragments) {
+    fragments.each((function(fragment) {
+      this.element.parentNode.insertBefore(fragment, this.element);
+    }).bind(this));
+  }
+});
+
+Insertion.Top = Class.create();
+Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(true);
+  },
+
+  insertContent: function(fragments) {
+    fragments.reverse(false).each((function(fragment) {
+      this.element.insertBefore(fragment, this.element.firstChild);
+    }).bind(this));
+  }
+});
+
+Insertion.Bottom = Class.create();
+Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
+  initializeRange: function() {
+    this.range.selectNodeContents(this.element);
+    this.range.collapse(this.element);
+  },
+
+  insertContent: function(fragments) {
+    fragments.each((function(fragment) {
+      this.element.appendChild(fragment);
+    }).bind(this));
+  }
+});
+
+Insertion.After = Class.create();
+Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
+  initializeRange: function() {
+    this.range.setStartAfter(this.element);
+  },
+
+  insertContent: function(fragments) {
+    fragments.each((function(fragment) {
+      this.element.parentNode.insertBefore(fragment,
+        this.element.nextSibling);
+    }).bind(this));
+  }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+  initialize: function(element) {
+    this.element = $(element);
+  },
+
+  _each: function(iterator) {
+    this.element.className.split(/\s+/).select(function(name) {
+      return name.length > 0;
+    })._each(iterator);
+  },
+
+  set: function(className) {
+    this.element.className = className;
+  },
+
+  add: function(classNameToAdd) {
+    if (this.include(classNameToAdd)) return;
+    this.set(this.toArray().concat(classNameToAdd).join(' '));
+  },
+
+  remove: function(classNameToRemove) {
+    if (!this.include(classNameToRemove)) return;
+    this.set(this.select(function(className) {
+      return className != classNameToRemove;
+    }).join(' '));
+  },
+
+  toString: function() {
+    return this.toArray().join(' ');
+  }
+}
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+var Selector = Class.create();
+Selector.prototype = {
+  initialize: function(expression) {
+    this.params = {classNames: []};
+    this.expression = expression.toString().strip();
+    this.parseExpression();
+    this.compileMatcher();
+  },
+
+  parseExpression: function() {
+    function abort(message) { throw 'Parse error in selector: ' + message; }
+
+    if (this.expression == '')  abort('empty expression');
+
+    var params = this.params, expr = this.expression, match, modifier, clause, rest;
+    while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
+      params.attributes = params.attributes || [];
+      params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
+      expr = match[1];
+    }
+
+    if (expr == '*') return this.params.wildcard = true;
+
+    while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
+      modifier = match[1], clause = match[2], rest = match[3];
+      switch (modifier) {
+        case '#':       params.id = clause; break;
+        case '.':       params.classNames.push(clause); break;
+        case '':
+        case undefined: params.tagName = clause.toUpperCase(); break;
+        default:        abort(expr.inspect());
+      }
+      expr = rest;
+    }
+
+    if (expr.length > 0) abort(expr.inspect());
+  },
+
+  buildMatchExpression: function() {
+    var params = this.params, conditions = [], clause;
+
+    if (params.wildcard)
+      conditions.push('true');
+    if (clause = params.id)
+      conditions.push('element.id == ' + clause.inspect());
+    if (clause = params.tagName)
+      conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
+    if ((clause = params.classNames).length > 0)
+      for (var i = 0; i < clause.length; i++)
+        conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
+    if (clause = params.attributes) {
+      clause.each(function(attribute) {
+        var value = 'element.getAttribute(' + attribute.name.inspect() + ')';
+        var splitValueBy = function(delimiter) {
+          return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
+        }
+
+        switch (attribute.operator) {
+          case '=':       conditions.push(value + ' == ' + attribute.value.inspect()); break;
+          case '~=':      conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
+          case '|=':      conditions.push(
+                            splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
+                          ); break;
+          case '!=':      conditions.push(value + ' != ' + attribute.value.inspect()); break;
+          case '':
+          case undefined: conditions.push(value + ' != null'); break;
+          default:        throw 'Unknown operator ' + attribute.operator + ' in selector';
+        }
+      });
+    }
+
+    return conditions.join(' && ');
+  },
+
+  compileMatcher: function() {
+    this.match = new Function('element', 'if (!element.tagName) return false; \
+      return ' + this.buildMatchExpression());
+  },
+
+  findElements: function(scope) {
+    var element;
+
+    if (element = $(this.params.id))
+      if (this.match(element))
+        if (!scope || Element.childOf(element, scope))
+          return [element];
+
+    scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
+
+    var results = [];
+    for (var i = 0; i < scope.length; i++)
+      if (this.match(element = scope[i]))
+        results.push(Element.extend(element));
+
+    return results;
+  },
+
+  toString: function() {
+    return this.expression;
+  }
+}
+
+function $$() {
+  return $A(arguments).map(function(expression) {
+    return expression.strip().split(/\s+/).inject([null], function(results, expr) {
+      var selector = new Selector(expr);
+      return results.map(selector.findElements.bind(selector)).flatten();
+    });
+  }).flatten();
+}
+var Field = {
+  clear: function() {
+    for (var i = 0; i < arguments.length; i++)
+      $(arguments[i]).value = '';
+  },
+
+  focus: function(element) {
+    $(element).focus();
+  },
+
+  present: function() {
+    for (var i = 0; i < arguments.length; i++)
+      if ($(arguments[i]).value == '') return false;
+    return true;
+  },
+
+  select: function(element) {
+    $(element).select();
+  },
+
+  activate: function(element) {
+    element = $(element);
+    element.focus();
+    if (element.select)
+      element.select();
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Form = {
+  serialize: function(form) {
+    var elements = Form.getElements($(form));
+    var queryComponents = new Array();
+
+    for (var i = 0; i < elements.length; i++) {
+      var queryComponent = Form.Element.serialize(elements[i]);
+      if (queryComponent)
+        queryComponents.push(queryComponent);
+    }
+
+    return queryComponents.join('&');
+  },
+
+  getElements: function(form) {
+    form = $(form);
+    var elements = new Array();
+
+    for (var tagName in Form.Element.Serializers) {
+      var tagElements = form.getElementsByTagName(tagName);
+      for (var j = 0; j < tagElements.length; j++)
+        elements.push(tagElements[j]);
+    }
+    return elements;
+  },
+
+  getInputs: function(form, typeName, name) {
+    form = $(form);
+    var inputs = form.getElementsByTagName('input');
+
+    if (!typeName && !name)
+      return inputs;
+
+    var matchingInputs = new Array();
+    for (var i = 0; i < inputs.length; i++) {
+      var input = inputs[i];
+      if ((typeName && input.type != typeName) ||
+          (name && input.name != name))
+        continue;
+      matchingInputs.push(input);
+    }
+
+    return matchingInputs;
+  },
+
+  disable: function(form) {
+    var elements = Form.getElements(form);
+    for (var i = 0; i < elements.length; i++) {
+      var element = elements[i];
+      element.blur();
+      element.disabled = 'true';
+    }
+  },
+
+  enable: function(form) {
+    var elements = Form.getElements(form);
+    for (var i = 0; i < elements.length; i++) {
+      var element = elements[i];
+      element.disabled = '';
+    }
+  },
+
+  findFirstElement: function(form) {
+    return Form.getElements(form).find(function(element) {
+      return element.type != 'hidden' && !element.disabled &&
+        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+    });
+  },
+
+  focusFirstElement: function(form) {
+    Field.activate(Form.findFirstElement(form));
+  },
+
+  reset: function(form) {
+    $(form).reset();
+  }
+}
+
+Form.Element = {
+  serialize: function(element) {
+    element = $(element);
+    var method = element.tagName.toLowerCase();
+    var parameter = Form.Element.Serializers[method](element);
+
+    if (parameter) {
+      var key = encodeURIComponent(parameter[0]);
+      if (key.length == 0) return;
+
+      if (parameter[1].constructor != Array)
+        parameter[1] = [parameter[1]];
+
+      return parameter[1].map(function(value) {
+        return key + '=' + encodeURIComponent(value);
+      }).join('&');
+    }
+  },
+
+  getValue: function(element) {
+    element = $(element);
+    var method = element.tagName.toLowerCase();
+    var parameter = Form.Element.Serializers[method](element);
+
+    if (parameter)
+      return parameter[1];
+  }
+}
+
+Form.Element.Serializers = {
+  input: function(element) {
+    switch (element.type.toLowerCase()) {
+      case 'submit':
+      case 'hidden':
+      case 'password':
+      case 'text':
+        return Form.Element.Serializers.textarea(element);
+      case 'checkbox':
+      case 'radio':
+        return Form.Element.Serializers.inputSelector(element);
+    }
+    return false;
+  },
+
+  inputSelector: function(element) {
+    if (element.checked)
+      return [element.name, element.value];
+  },
+
+  textarea: function(element) {
+    return [element.name, element.value];
+  },
+
+  select: function(element) {
+    return Form.Element.Serializers[element.type == 'select-one' ?
+      'selectOne' : 'selectMany'](element);
+  },
+
+  selectOne: function(element) {
+    var value = '', opt, index = element.selectedIndex;
+    if (index >= 0) {
+      opt = element.options[index];
+      value = opt.value || opt.text;
+    }
+    return [element.name, value];
+  },
+
+  selectMany: function(element) {
+    var value = [];
+    for (var i = 0; i < element.length; i++) {
+      var opt = element.options[i];
+      if (opt.selected)
+        value.push(opt.value || opt.text);
+    }
+    return [element.name, value];
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var $F = Form.Element.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = function() {}
+Abstract.TimedObserver.prototype = {
+  initialize: function(element, frequency, callback) {
+    this.frequency = frequency;
+    this.element   = $(element);
+    this.callback  = callback;
+
+    this.lastValue = this.getValue();
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  onTimerEvent: function() {
+    var value = this.getValue();
+    if (this.lastValue != value) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  }
+}
+
+Form.Element.Observer = Class.create();
+Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.Observer = Class.create();
+Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = function() {}
+Abstract.EventObserver.prototype = {
+  initialize: function(element, callback) {
+    this.element  = $(element);
+    this.callback = callback;
+
+    this.lastValue = this.getValue();
+    if (this.element.tagName.toLowerCase() == 'form')
+      this.registerFormCallbacks();
+    else
+      this.registerCallback(this.element);
+  },
+
+  onElementEvent: function() {
+    var value = this.getValue();
+    if (this.lastValue != value) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  },
+
+  registerFormCallbacks: function() {
+    var elements = Form.getElements(this.element);
+    for (var i = 0; i < elements.length; i++)
+      this.registerCallback(elements[i]);
+  },
+
+  registerCallback: function(element) {
+    if (element.type) {
+      switch (element.type.toLowerCase()) {
+        case 'checkbox':
+        case 'radio':
+          Event.observe(element, 'click', this.onElementEvent.bind(this));
+          break;
+        case 'password':
+        case 'text':
+        case 'textarea':
+        case 'select-one':
+        case 'select-multiple':
+          Event.observe(element, 'change', this.onElementEvent.bind(this));
+          break;
+      }
+    }
+  }
+}
+
+Form.Element.EventObserver = Class.create();
+Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.EventObserver = Class.create();
+Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+if (!window.Event) {
+  var Event = new Object();
+}
+
+Object.extend(Event, {
+  KEY_BACKSPACE: 8,
+  KEY_TAB:       9,
+  KEY_RETURN:   13,
+  KEY_ESC:      27,
+  KEY_LEFT:     37,
+  KEY_UP:       38,
+  KEY_RIGHT:    39,
+  KEY_DOWN:     40,
+  KEY_DELETE:   46,
+
+  element: function(event) {
+    return event.target || event.srcElement;
+  },
+
+  isLeftClick: function(event) {
+    return (((event.which) && (event.which == 1)) ||
+            ((event.button) && (event.button == 1)));
+  },
+
+  pointerX: function(event) {
+    return event.pageX || (event.clientX +
+      (document.documentElement.scrollLeft || document.body.scrollLeft));
+  },
+
+  pointerY: function(event) {
+    return event.pageY || (event.clientY +
+      (document.documentElement.scrollTop || document.body.scrollTop));
+  },
+
+  stop: function(event) {
+    if (event.preventDefault) {
+      event.preventDefault();
+      event.stopPropagation();
+    } else {
+      event.returnValue = false;
+      event.cancelBubble = true;
+    }
+  },
+
+  // find the first node with the given tagName, starting from the
+  // node the event was triggered on; traverses the DOM upwards
+  findElement: function(event, tagName) {
+    var element = Event.element(event);
+    while (element.parentNode && (!element.tagName ||
+        (element.tagName.toUpperCase() != tagName.toUpperCase())))
+      element = element.parentNode;
+    return element;
+  },
+
+  observers: false,
+
+  _observeAndCache: function(element, name, observer, useCapture) {
+    if (!this.observers) this.observers = [];
+    if (element.addEventListener) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.addEventListener(name, observer, useCapture);
+    } else if (element.attachEvent) {
+      this.observers.push([element, name, observer, useCapture]);
+      element.attachEvent('on' + name, observer);
+    }
+  },
+
+  unloadCache: function() {
+    if (!Event.observers) return;
+    for (var i = 0; i < Event.observers.length; i++) {
+      Event.stopObserving.apply(this, Event.observers[i]);
+      Event.observers[i][0] = null;
+    }
+    Event.observers = false;
+  },
+
+  observe: function(element, name, observer, useCapture) {
+    var element = $(element);
+    useCapture = useCapture || false;
+
+    if (name == 'keypress' &&
+        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
+        || element.attachEvent))
+      name = 'keydown';
+
+    this._observeAndCache(element, name, observer, useCapture);
+  },
+
+  stopObserving: function(element, name, observer, useCapture) {
+    var element = $(element);
+    useCapture = useCapture || false;
+
+    if (name == 'keypress' &&
+        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
+        || element.detachEvent))
+      name = 'keydown';
+
+    if (element.removeEventListener) {
+      element.removeEventListener(name, observer, useCapture);
+    } else if (element.detachEvent) {
+      element.detachEvent('on' + name, observer);
+    }
+  }
+});
+
+/* prevent memory leaks in IE */
+if (navigator.appVersion.match(/\bMSIE\b/))
+  Event.observe(window, 'unload', Event.unloadCache, false);
+var Position = {
+  // set to true if needed, warning: firefox performance problems
+  // NOT neeeded for page scrolling, only if draggable contained in
+  // scrollable elements
+  includeScrollOffsets: false,
+
+  // must be called before calling withinIncludingScrolloffset, every time the
+  // page is scrolled
+  prepare: function() {
+    this.deltaX =  window.pageXOffset
+                || document.documentElement.scrollLeft
+                || document.body.scrollLeft
+                || 0;
+    this.deltaY =  window.pageYOffset
+                || document.documentElement.scrollTop
+                || document.body.scrollTop
+                || 0;
+  },
+
+  realOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.scrollTop  || 0;
+      valueL += element.scrollLeft || 0;
+      element = element.parentNode;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  cumulativeOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  positionedOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+      if (element) {
+        p = Element.getStyle(element, 'position');
+        if (p == 'relative' || p == 'absolute') break;
+      }
+    } while (element);
+    return [valueL, valueT];
+  },
+
+  offsetParent: function(element) {
+    if (element.offsetParent) return element.offsetParent;
+    if (element == document.body) return element;
+
+    while ((element = element.parentNode) && element != document.body)
+      if (Element.getStyle(element, 'position') != 'static')
+        return element;
+
+    return document.body;
+  },
+
+  // caches x/y coordinate pair to use with overlap
+  within: function(element, x, y) {
+    if (this.includeScrollOffsets)
+      return this.withinIncludingScrolloffsets(element, x, y);
+    this.xcomp = x;
+    this.ycomp = y;
+    this.offset = this.cumulativeOffset(element);
+
+    return (y >= this.offset[1] &&
+            y <  this.offset[1] + element.offsetHeight &&
+            x >= this.offset[0] &&
+            x <  this.offset[0] + element.offsetWidth);
+  },
+
+  withinIncludingScrolloffsets: function(element, x, y) {
+    var offsetcache = this.realOffset(element);
+
+    this.xcomp = x + offsetcache[0] - this.deltaX;
+    this.ycomp = y + offsetcache[1] - this.deltaY;
+    this.offset = this.cumulativeOffset(element);
+
+    return (this.ycomp >= this.offset[1] &&
+            this.ycomp <  this.offset[1] + element.offsetHeight &&
+            this.xcomp >= this.offset[0] &&
+            this.xcomp <  this.offset[0] + element.offsetWidth);
+  },
+
+  // within must be called directly before
+  overlap: function(mode, element) {
+    if (!mode) return 0;
+    if (mode == 'vertical')
+      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+        element.offsetHeight;
+    if (mode == 'horizontal')
+      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+        element.offsetWidth;
+  },
+
+  clone: function(source, target) {
+    source = $(source);
+    target = $(target);
+    target.style.position = 'absolute';
+    var offsets = this.cumulativeOffset(source);
+    target.style.top    = offsets[1] + 'px';
+    target.style.left   = offsets[0] + 'px';
+    target.style.width  = source.offsetWidth + 'px';
+    target.style.height = source.offsetHeight + 'px';
+  },
+
+  page: function(forElement) {
+    var valueT = 0, valueL = 0;
+
+    var element = forElement;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+
+      // Safari fix
+      if (element.offsetParent==document.body)
+        if (Element.getStyle(element,'position')=='absolute') break;
+
+    } while (element = element.offsetParent);
+
+    element = forElement;
+    do {
+      valueT -= element.scrollTop  || 0;
+      valueL -= element.scrollLeft || 0;
+    } while (element = element.parentNode);
+
+    return [valueL, valueT];
+  },
+
+  clone: function(source, target) {
+    var options = Object.extend({
+      setLeft:    true,
+      setTop:     true,
+      setWidth:   true,
+      setHeight:  true,
+      offsetTop:  0,
+      offsetLeft: 0
+    }, arguments[2] || {})
+
+    // find page position of source
+    source = $(source);
+    var p = Position.page(source);
+
+    // find coordinate system to use
+    target = $(target);
+    var delta = [0, 0];
+    var parent = null;
+    // delta [0,0] will do fine with position: fixed elements,
+    // position:absolute needs offsetParent deltas
+    if (Element.getStyle(target,'position') == 'absolute') {
+      parent = Position.offsetParent(target);
+      delta = Position.page(parent);
+    }
+
+    // correct by body offsets (fixes Safari)
+    if (parent == document.body) {
+      delta[0] -= document.body.offsetLeft;
+      delta[1] -= document.body.offsetTop;
+    }
+
+    // set position
+    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
+    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
+    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
+    if(options.setHeight) target.style.height = source.offsetHeight + 'px';
+  },
+
+  absolutize: function(element) {
+    element = $(element);
+    if (element.style.position == 'absolute') return;
+    Position.prepare();
+
+    var offsets = Position.positionedOffset(element);
+    var top     = offsets[1];
+    var left    = offsets[0];
+    var width   = element.clientWidth;
+    var height  = element.clientHeight;
+
+    element._originalLeft   = left - parseFloat(element.style.left  || 0);
+    element._originalTop    = top  - parseFloat(element.style.top || 0);
+    element._originalWidth  = element.style.width;
+    element._originalHeight = element.style.height;
+
+    element.style.position = 'absolute';
+    element.style.top    = top + 'px';;
+    element.style.left   = left + 'px';;
+    element.style.width  = width + 'px';;
+    element.style.height = height + 'px';;
+  },
+
+  relativize: function(element) {
+    element = $(element);
+    if (element.style.position == 'relative') return;
+    Position.prepare();
+
+    element.style.position = 'relative';
+    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
+    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+    element.style.top    = top + 'px';
+    element.style.left   = left + 'px';
+    element.style.height = element._originalHeight;
+    element.style.width  = element._originalWidth;
+  }
+}
+
+// Safari returns margins on body which is incorrect if the child is absolutely
+// positioned.  For performance reasons, redefine Position.cumulativeOffset for
+// KHTML/WebKit only.
+if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
+  Position.cumulativeOffset = function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      if (element.offsetParent == document.body)
+        if (Element.getStyle(element, 'position') == 'absolute') break;
+
+      element = element.offsetParent;
+    } while (element);
+
+    return [valueL, valueT];
+  }
+}
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/scriptaculous.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/scriptaculous.js
new file mode 100644 (file)
index 0000000..f61fc57
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// 
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var Scriptaculous = {
+  Version: '1.6.1',
+  require: function(libraryName) {
+    // inserting via DOM fails in Safari 2.0, so brute force approach
+    document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
+  },
+  load: function() {
+    if((typeof Prototype=='undefined') || 
+       (typeof Element == 'undefined') || 
+       (typeof Element.Methods=='undefined') ||
+       parseFloat(Prototype.Version.split(".")[0] + "." +
+                  Prototype.Version.split(".")[1]) < 1.5)
+       throw("script.aculo.us requires the Prototype JavaScript framework >= 1.5.0");
+    
+    $A(document.getElementsByTagName("script")).findAll( function(s) {
+      return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+    }).each( function(s) {
+      var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+      var includes = s.src.match(/\?.*load=([a-z,]*)/);
+      (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider').split(',').each(
+       function(include) { Scriptaculous.require(path+include+'.js') });
+    });
+  }
+}
+
+Scriptaculous.load();
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/slider.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/slider.js
new file mode 100644 (file)
index 0000000..c0f1fc0
--- /dev/null
@@ -0,0 +1,283 @@
+// Copyright (c) 2005 Marty Haught, Thomas Fuchs 
+//
+// See http://script.aculo.us for more info
+// 
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+if(!Control) var Control = {};
+Control.Slider = Class.create();
+
+// options:
+//  axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+//  onChange(value)
+//  onSlide(value)
+Control.Slider.prototype = {
+  initialize: function(handle, track, options) {
+    var slider = this;
+    
+    if(handle instanceof Array) {
+      this.handles = handle.collect( function(e) { return $(e) });
+    } else {
+      this.handles = [$(handle)];
+    }
+    
+    this.track   = $(track);
+    this.options = options || {};
+
+    this.axis      = this.options.axis || 'horizontal';
+    this.increment = this.options.increment || 1;
+    this.step      = parseInt(this.options.step || '1');
+    this.range     = this.options.range || $R(0,1);
+    
+    this.value     = 0; // assure backwards compat
+    this.values    = this.handles.map( function() { return 0 });
+    this.spans     = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+    this.options.startSpan = $(this.options.startSpan || null);
+    this.options.endSpan   = $(this.options.endSpan || null);
+
+    this.restricted = this.options.restricted || false;
+
+    this.maximum   = this.options.maximum || this.range.end;
+    this.minimum   = this.options.minimum || this.range.start;
+
+    // Will be used to align the handle onto the track, if necessary
+    this.alignX = parseInt(this.options.alignX || '0');
+    this.alignY = parseInt(this.options.alignY || '0');
+    
+    this.trackLength = this.maximumOffset() - this.minimumOffset();
+    this.handleLength = this.isVertical() ? this.handles[0].offsetHeight : this.handles[0].offsetWidth;
+
+    this.active   = false;
+    this.dragging = false;
+    this.disabled = false;
+
+    if(this.options.disabled) this.setDisabled();
+
+    // Allowed values array
+    this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+    if(this.allowedValues) {
+      this.minimum = this.allowedValues.min();
+      this.maximum = this.allowedValues.max();
+    }
+
+    this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+    this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
+    this.eventMouseMove = this.update.bindAsEventListener(this);
+
+    // Initialize handles in reverse (make sure first handle is active)
+    this.handles.each( function(h,i) {
+      i = slider.handles.length-1-i;
+      slider.setValue(parseFloat(
+        (slider.options.sliderValue instanceof Array ? 
+          slider.options.sliderValue[i] : slider.options.sliderValue) || 
+         slider.range.start), i);
+      Element.makePositioned(h); // fix IE
+      Event.observe(h, "mousedown", slider.eventMouseDown);
+    });
+    
+    Event.observe(this.track, "mousedown", this.eventMouseDown);
+    Event.observe(document, "mouseup", this.eventMouseUp);
+    Event.observe(document, "mousemove", this.eventMouseMove);
+    
+    this.initialized = true;
+  },
+  dispose: function() {
+    var slider = this;    
+    Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+    Event.stopObserving(document, "mouseup", this.eventMouseUp);
+    Event.stopObserving(document, "mousemove", this.eventMouseMove);
+    this.handles.each( function(h) {
+      Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+    });
+  },
+  setDisabled: function(){
+    this.disabled = true;
+  },
+  setEnabled: function(){
+    this.disabled = false;
+  },  
+  getNearestValue: function(value){
+    if(this.allowedValues){
+      if(value >= this.allowedValues.max()) return(this.allowedValues.max());
+      if(value <= this.allowedValues.min()) return(this.allowedValues.min());
+      
+      var offset = Math.abs(this.allowedValues[0] - value);
+      var newValue = this.allowedValues[0];
+      this.allowedValues.each( function(v) {
+        var currentOffset = Math.abs(v - value);
+        if(currentOffset <= offset){
+          newValue = v;
+          offset = currentOffset;
+        } 
+      });
+      return newValue;
+    }
+    if(value > this.range.end) return this.range.end;
+    if(value < this.range.start) return this.range.start;
+    return value;
+  },
+  setValue: function(sliderValue, handleIdx){
+    if(!this.active) {
+      this.activeHandle    = this.handles[handleIdx];
+      this.activeHandleIdx = handleIdx;
+      this.updateStyles();
+    }
+    handleIdx = handleIdx || this.activeHandleIdx || 0;
+    if(this.initialized && this.restricted) {
+      if((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+        sliderValue = this.values[handleIdx-1];
+      if((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+        sliderValue = this.values[handleIdx+1];
+    }
+    sliderValue = this.getNearestValue(sliderValue);
+    this.values[handleIdx] = sliderValue;
+    this.value = this.values[0]; // assure backwards compat
+    
+    this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] = 
+      this.translateToPx(sliderValue);
+    
+    this.drawSpans();
+    if(!this.dragging || !this.event) this.updateFinished();
+  },
+  setValueBy: function(delta, handleIdx) {
+    this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta, 
+      handleIdx || this.activeHandleIdx || 0);
+  },
+  translateToPx: function(value) {
+    return Math.round(
+      ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) * 
+      (value - this.range.start)) + "px";
+  },
+  translateToValue: function(offset) {
+    return ((offset/(this.trackLength-this.handleLength) * 
+      (this.range.end-this.range.start)) + this.range.start);
+  },
+  getRange: function(range) {
+    var v = this.values.sortBy(Prototype.K); 
+    range = range || 0;
+    return $R(v[range],v[range+1]);
+  },
+  minimumOffset: function(){
+    return(this.isVertical() ? this.alignY : this.alignX);
+  },
+  maximumOffset: function(){
+    return(this.isVertical() ?
+      this.track.offsetHeight - this.alignY : this.track.offsetWidth - this.alignX);
+  },  
+  isVertical:  function(){
+    return (this.axis == 'vertical');
+  },
+  drawSpans: function() {
+    var slider = this;
+    if(this.spans)
+      $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+    if(this.options.startSpan)
+      this.setSpan(this.options.startSpan,
+        $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+    if(this.options.endSpan)
+      this.setSpan(this.options.endSpan, 
+        $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+  },
+  setSpan: function(span, range) {
+    if(this.isVertical()) {
+      span.style.top = this.translateToPx(range.start);
+      span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+    } else {
+      span.style.left = this.translateToPx(range.start);
+      span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+    }
+  },
+  updateStyles: function() {
+    this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+    Element.addClassName(this.activeHandle, 'selected');
+  },
+  startDrag: function(event) {
+    if(Event.isLeftClick(event)) {
+      if(!this.disabled){
+        this.active = true;
+        
+        var handle = Event.element(event);
+        var pointer  = [Event.pointerX(event), Event.pointerY(event)];
+        if(handle==this.track) {
+          var offsets  = Position.cumulativeOffset(this.track); 
+          this.event = event;
+          this.setValue(this.translateToValue( 
+           (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+          ));
+          var offsets  = Position.cumulativeOffset(this.activeHandle);
+          this.offsetX = (pointer[0] - offsets[0]);
+          this.offsetY = (pointer[1] - offsets[1]);
+        } else {
+          // find the handle (prevents issues with Safari)
+          while((this.handles.indexOf(handle) == -1) && handle.parentNode) 
+            handle = handle.parentNode;
+        
+          this.activeHandle    = handle;
+          this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+          this.updateStyles();
+        
+          var offsets  = Position.cumulativeOffset(this.activeHandle);
+          this.offsetX = (pointer[0] - offsets[0]);
+          this.offsetY = (pointer[1] - offsets[1]);
+        }
+      }
+      Event.stop(event);
+    }
+  },
+  update: function(event) {
+   if(this.active) {
+      if(!this.dragging) this.dragging = true;
+      this.draw(event);
+      // fix AppleWebKit rendering
+      if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
+      Event.stop(event);
+   }
+  },
+  draw: function(event) {
+    var pointer = [Event.pointerX(event), Event.pointerY(event)];
+    var offsets = Position.cumulativeOffset(this.track);
+    pointer[0] -= this.offsetX + offsets[0];
+    pointer[1] -= this.offsetY + offsets[1];
+    this.event = event;
+    this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+    if(this.initialized && this.options.onSlide)
+      this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+  },
+  endDrag: function(event) {
+    if(this.active && this.dragging) {
+      this.finishDrag(event, true);
+      Event.stop(event);
+    }
+    this.active = false;
+    this.dragging = false;
+  },  
+  finishDrag: function(event, success) {
+    this.active = false;
+    this.dragging = false;
+    this.updateFinished();
+  },
+  updateFinished: function() {
+    if(this.initialized && this.options.onChange) 
+      this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+    this.event = null;
+  }
+}
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/unittest.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/lib/unittest.js
new file mode 100644 (file)
index 0000000..d2c2d81
--- /dev/null
@@ -0,0 +1,383 @@
+// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//           (c) 2005 Jon Tirsen (http://www.tirsen.com)
+//           (c) 2005 Michael Schuerig (http://www.schuerig.de/michael/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+// experimental, Firefox-only
+Event.simulateMouse = function(element, eventName) {
+  var options = Object.extend({
+    pointerX: 0,
+    pointerY: 0,
+    buttons: 0
+  }, arguments[2] || {});
+  var oEvent = document.createEvent("MouseEvents");
+  oEvent.initMouseEvent(eventName, true, true, document.defaultView, 
+    options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY, 
+    false, false, false, false, 0, $(element));
+  
+  if(this.mark) Element.remove(this.mark);
+  this.mark = document.createElement('div');
+  this.mark.appendChild(document.createTextNode(" "));
+  document.body.appendChild(this.mark);
+  this.mark.style.position = 'absolute';
+  this.mark.style.top = options.pointerY + "px";
+  this.mark.style.left = options.pointerX + "px";
+  this.mark.style.width = "5px";
+  this.mark.style.height = "5px;";
+  this.mark.style.borderTop = "1px solid red;"
+  this.mark.style.borderLeft = "1px solid red;"
+  
+  if(this.step)
+    alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
+  
+  $(element).dispatchEvent(oEvent);
+};
+
+// Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2.
+// You need to downgrade to 1.0.4 for now to get this working
+// See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
+Event.simulateKey = function(element, eventName) {
+  var options = Object.extend({
+    ctrlKey: false,
+    altKey: false,
+    shiftKey: false,
+    metaKey: false,
+    keyCode: 0,
+    charCode: 0
+  }, arguments[2] || {});
+
+  var oEvent = document.createEvent("KeyEvents");
+  oEvent.initKeyEvent(eventName, true, true, window, 
+    options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
+    options.keyCode, options.charCode );
+  $(element).dispatchEvent(oEvent);
+};
+
+Event.simulateKeys = function(element, command) {
+  for(var i=0; i<command.length; i++) {
+    Event.simulateKey(element,'keypress',{charCode:command.charCodeAt(i)});
+  }
+};
+
+var Test = {}
+Test.Unit = {};
+
+// security exception workaround
+Test.Unit.inspect = Object.inspect;
+
+Test.Unit.Logger = Class.create();
+Test.Unit.Logger.prototype = {
+  initialize: function(log) {
+    this.log = $(log);
+    if (this.log) {
+      this._createLogTable();
+    }
+  },
+  start: function(testName) {
+    if (!this.log) return;
+    this.testName = testName;
+    this.lastLogLine = document.createElement('tr');
+    this.statusCell = document.createElement('td');
+    this.nameCell = document.createElement('td');
+    this.nameCell.appendChild(document.createTextNode(testName));
+    this.messageCell = document.createElement('td');
+    this.lastLogLine.appendChild(this.statusCell);
+    this.lastLogLine.appendChild(this.nameCell);
+    this.lastLogLine.appendChild(this.messageCell);
+    this.loglines.appendChild(this.lastLogLine);
+  },
+  finish: function(status, summary) {
+    if (!this.log) return;
+    this.lastLogLine.className = status;
+    this.statusCell.innerHTML = status;
+    this.messageCell.innerHTML = this._toHTML(summary);
+  },
+  message: function(message) {
+    if (!this.log) return;
+    this.messageCell.innerHTML = this._toHTML(message);
+  },
+  summary: function(summary) {
+    if (!this.log) return;
+    this.logsummary.innerHTML = this._toHTML(summary);
+  },
+  _createLogTable: function() {
+    this.log.innerHTML =
+    '<div id="logsummary"></div>' +
+    '<table id="logtable">' +
+    '<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
+    '<tbody id="loglines"></tbody>' +
+    '</table>';
+    this.logsummary = $('logsummary')
+    this.loglines = $('loglines');
+  },
+  _toHTML: function(txt) {
+    return txt.escapeHTML().replace(/\n/g,"<br/>");
+  }
+}
+
+Test.Unit.Runner = Class.create();
+Test.Unit.Runner.prototype = {
+  initialize: function(testcases) {
+    this.options = Object.extend({
+      testLog: 'testlog'
+    }, arguments[1] || {});
+    this.options.resultsURL = this.parseResultsURLQueryParameter();
+    if (this.options.testLog) {
+      this.options.testLog = $(this.options.testLog) || null;
+    }
+    if(this.options.tests) {
+      this.tests = [];
+      for(var i = 0; i < this.options.tests.length; i++) {
+        if(/^test/.test(this.options.tests[i])) {
+          this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"]));
+        }
+      }
+    } else {
+      if (this.options.test) {
+        this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])];
+      } else {
+        this.tests = [];
+        for(var testcase in testcases) {
+          if(/^test/.test(testcase)) {
+            this.tests.push(new Test.Unit.Testcase(testcase, testcases[testcase], testcases["setup"], testcases["teardown"]));
+          }
+        }
+      }
+    }
+    this.currentTest = 0;
+    this.logger = new Test.Unit.Logger(this.options.testLog);
+    setTimeout(this.runTests.bind(this), 1000);
+  },
+  parseResultsURLQueryParameter: function() {
+    return window.location.search.parseQuery()["resultsURL"];
+  },
+  // Returns:
+  //  "ERROR" if there was an error,
+  //  "FAILURE" if there was a failure, or
+  //  "SUCCESS" if there was neither
+  getResult: function() {
+    var hasFailure = false;
+    for(var i=0;i<this.tests.length;i++) {
+      if (this.tests[i].errors > 0) {
+        return "ERROR";
+      }
+      if (this.tests[i].failures > 0) {
+        hasFailure = true;
+      }
+    }
+    if (hasFailure) {
+      return "FAILURE";
+    } else {
+      return "SUCCESS";
+    }
+  },
+  postResults: function() {
+    if (this.options.resultsURL) {
+      new Ajax.Request(this.options.resultsURL, 
+        { method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false });
+    }
+  },
+  runTests: function() {
+    var test = this.tests[this.currentTest];
+    if (!test) {
+      // finished!
+      this.postResults();
+      this.logger.summary(this.summary());
+      return;
+    }
+    if(!test.isWaiting) {
+      this.logger.start(test.name);
+    }
+    test.run();
+    if(test.isWaiting) {
+      this.logger.message("Waiting for " + test.timeToWait + "ms");
+      setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
+    } else {
+      this.logger.finish(test.status(), test.summary());
+      this.currentTest++;
+      // tail recursive, hopefully the browser will skip the stackframe
+      this.runTests();
+    }
+  },
+  summary: function() {
+    var assertions = 0;
+    var failures = 0;
+    var errors = 0;
+    var messages = [];
+    for(var i=0;i<this.tests.length;i++) {
+      assertions +=   this.tests[i].assertions;
+      failures   +=   this.tests[i].failures;
+      errors     +=   this.tests[i].errors;
+    }
+    return (
+      this.tests.length + " tests, " + 
+      assertions + " assertions, " + 
+      failures   + " failures, " +
+      errors     + " errors");
+  }
+}
+
+Test.Unit.Assertions = Class.create();
+Test.Unit.Assertions.prototype = {
+  initialize: function() {
+    this.assertions = 0;
+    this.failures   = 0;
+    this.errors     = 0;
+    this.messages   = [];
+  },
+  summary: function() {
+    return (
+      this.assertions + " assertions, " + 
+      this.failures   + " failures, " +
+      this.errors     + " errors" + "\n" +
+      this.messages.join("\n"));
+  },
+  pass: function() {
+    this.assertions++;
+  },
+  fail: function(message) {
+    this.failures++;
+    this.messages.push("Failure: " + message);
+  },
+  info: function(message) {
+    this.messages.push("Info: " + message);
+  },
+  error: function(error) {
+    this.errors++;
+    this.messages.push(error.name + ": "+ error.message + "(" + Test.Unit.inspect(error) +")");
+  },
+  status: function() {
+    if (this.failures > 0) return 'failed';
+    if (this.errors > 0) return 'error';
+    return 'passed';
+  },
+  assert: function(expression) {
+    var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"';
+    try { expression ? this.pass() : 
+      this.fail(message); }
+    catch(e) { this.error(e); }
+  },
+  assertEqual: function(expected, actual) {
+    var message = arguments[2] || "assertEqual";
+    try { (expected == actual) ? this.pass() :
+      this.fail(message + ': expected "' + Test.Unit.inspect(expected) + 
+        '", actual "' + Test.Unit.inspect(actual) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertEnumEqual: function(expected, actual) {
+    var message = arguments[2] || "assertEnumEqual";
+    try { $A(expected).length == $A(actual).length && 
+      expected.zip(actual).all(function(pair) { return pair[0] == pair[1] }) ?
+        this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) + 
+          ', actual ' + Test.Unit.inspect(actual)); }
+    catch(e) { this.error(e); }
+  },
+  assertNotEqual: function(expected, actual) {
+    var message = arguments[2] || "assertNotEqual";
+    try { (expected != actual) ? this.pass() : 
+      this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertNull: function(obj) {
+    var message = arguments[1] || 'assertNull'
+    try { (obj==null) ? this.pass() : 
+      this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertHidden: function(element) {
+    var message = arguments[1] || 'assertHidden';
+    this.assertEqual("none", element.style.display, message);
+  },
+  assertNotNull: function(object) {
+    var message = arguments[1] || 'assertNotNull';
+    this.assert(object != null, message);
+  },
+  assertInstanceOf: function(expected, actual) {
+    var message = arguments[2] || 'assertInstanceOf';
+    try { 
+      (actual instanceof expected) ? this.pass() : 
+      this.fail(message + ": object was not an instance of the expected type"); }
+    catch(e) { this.error(e); } 
+  },
+  assertNotInstanceOf: function(expected, actual) {
+    var message = arguments[2] || 'assertNotInstanceOf';
+    try { 
+      !(actual instanceof expected) ? this.pass() : 
+      this.fail(message + ": object was an instance of the not expected type"); }
+    catch(e) { this.error(e); } 
+  },
+  _isVisible: function(element) {
+    element = $(element);
+    if(!element.parentNode) return true;
+    this.assertNotNull(element);
+    if(element.style && Element.getStyle(element, 'display') == 'none')
+      return false;
+    
+    return this._isVisible(element.parentNode);
+  },
+  assertNotVisible: function(element) {
+    this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1]));
+  },
+  assertVisible: function(element) {
+    this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1]));
+  },
+  benchmark: function(operation, iterations) {
+    var startAt = new Date();
+    (iterations || 1).times(operation);
+    var timeTaken = ((new Date())-startAt);
+    this.info((arguments[2] || 'Operation') + ' finished ' + 
+       iterations + ' iterations in ' + (timeTaken/1000)+'s' );
+    return timeTaken;
+  }
+}
+
+Test.Unit.Testcase = Class.create();
+Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), {
+  initialize: function(name, test, setup, teardown) {
+    Test.Unit.Assertions.prototype.initialize.bind(this)();
+    this.name           = name;
+    this.test           = test || function() {};
+    this.setup          = setup || function() {};
+    this.teardown       = teardown || function() {};
+    this.isWaiting      = false;
+    this.timeToWait     = 1000;
+  },
+  wait: function(time, nextPart) {
+    this.isWaiting = true;
+    this.test = nextPart;
+    this.timeToWait = time;
+  },
+  run: function() {
+    try {
+      try {
+        if (!this.isWaiting) this.setup.bind(this)();
+        this.isWaiting = false;
+        this.test.bind(this)();
+      } finally {
+        if(!this.isWaiting) {
+          this.teardown.bind(this)();
+        }
+      }
+    }
+    catch(e) { this.error(e); }
+  }
+});
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/licence.txt b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/licence.txt
new file mode 100644 (file)
index 0000000..b59e029
--- /dev/null
@@ -0,0 +1,12 @@
+Copyright (c) 2006, David Spurr (www.defusion.org.uk)\r
+All rights reserved.\r
+\r
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\r
+\r
+    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\r
+    * 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.\r
+    * Neither the name of the David Spurr nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\r
+\r
+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.\r
+\r
+http://www.opensource.org/licenses/bsd-license.php
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/marqueeHoriz.gif b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/marqueeHoriz.gif
new file mode 100644 (file)
index 0000000..25317e5
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/marqueeHoriz.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/marqueeVert.gif b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/marqueeVert.gif
new file mode 100644 (file)
index 0000000..354070b
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/marqueeVert.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/plugin.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/plugin.css
new file mode 100644 (file)
index 0000000..72ed041
--- /dev/null
@@ -0,0 +1,4 @@
+.kfm_plugin_cropper_contexticon{
+       background-image:url(img/crop.gif);
+       background-repeat:no-repeat;
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/plugin.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/cropper/plugin.js
new file mode 100644 (file)
index 0000000..45e8143
--- /dev/null
@@ -0,0 +1,87 @@
+function plugin_cropper(){
+       /*defaults*/
+       this.name="cropper";
+       this.mode=0; //single files only
+       this.title="Crop";
+       this.extensions=["jpg","png","gif"];
+       this.category="edit";
+       this.writable=0; // non writable default
+
+       this.crop_to_new=function(fid){
+               var data=File_getInstance(fid[0]);
+               var url='plugins/cropper/croparea.php?id='+fid+'&width='+data.width+'&height='+data.height;
+               kfm_pluginIframeShow(url);
+               kfm_pluginIframeButton('kfm_cropToNew('+fid+',kfm_pluginIframeVar("coordinates"),kfm_pluginIframeVar("dimensions"))','Crop to new file');
+               //this.openCropper(fid,url);
+       }
+       this.crop_image=function(fid){
+               var data=File_getInstance(fid[0]);
+               var url='plugins/cropper/croparea.php?id='+fid+'&width='+data.width+'&height='+data.height+'&options=both';
+               var ifr=kfm_pluginIframeShow(url);
+               kfm_pluginIframeButton('kfm_cropToOriginal('+fid+',kfm_pluginIframeVar("coordinates"),kfm_pluginIframeVar("dimensions"))','Crop');
+               kfm_pluginIframeButton('kfm_cropToNew('+fid+',kfm_pluginIframeVar("coordinates"),kfm_pluginIframeVar("dimensions"))','Crop to new file');
+               //this.openCropper(fid,url);
+       }
+}
+       function kfm_cropToOriginal(id,coords,dimensions){
+               if(!coords || !dimensions)return;
+               kfm_fileLoader(id);
+               var F=File_getInstance(id);
+               kfm_pluginIframeHide();
+               x_kfm_cropToOriginal(id, coords.x1, coords.y1, dimensions.width, dimensions.height, function(id){
+                       if($type(id)=='string')return kfm_log(id);
+                       F.setThumbnailBackground($('kfm_file_icon_'+id),true);
+               });
+       }
+       function kfm_cropToNew(id, coords, dimensions){
+               if(!coords || !dimensions)return;
+               F=File_getInstance(id);
+               var filename=F.name;
+               var newname_suggestion=filename.substr(0,filename.length-F.ext.length-1)+'.cropped.'+F.ext;
+               var html=kfm.lang.Filename+'<br/>';
+               html+='<input type="text" id="crop_new_filename" value="'+newname_suggestion+'" size="'+(newname_suggestion.length+1)+'" />';
+               $j.prompt(html,{
+                       buttons:{Cancel:false,OK:true},
+                       callback:function(v,m){
+                               if(!v)return;
+                               newName=m.children('#crop_new_filename').val();
+                               if(!newName||newName==filename)return;
+                               kfm_pluginIframeHide();
+                               x_kfm_cropToNew(id, coords.x1, coords.y1, dimensions.width, dimensions.height, newName, kfm_refreshFiles);
+                       }
+               });
+       }
+
+/* add plugins to the hook system */
+kfm_addHook(new plugin_cropper(),
+       {mode:0,"extensions":["jpg","png","gif"], "category":"edit", "writable":1, title:"Crop image", doFunction:"crop_image"}
+);
+kfm_addHook(new plugin_cropper(),
+       {mode:0,"extensions":["jpg","png","gif"], "category":"edit", "writable":0, title:"Crop to new image", doFunction:"crop_to_new"}
+);
+
+
+/** Temporary dump function, dumps no functions to avoid prototype functions */
+function dump(arr,level) {
+       var dumped_text = "";
+       if(!level) level = 0;
+       var level_padding = "";
+       for(var j=0;j<level+1;j++) level_padding += "    ";
+
+       if(typeof(arr) == 'object') { //Array/Hashes/Objects
+               for(var item in arr) {
+                       
+                       var value = arr[item];
+                       if(typeof(value)=="function")continue;
+                       if(typeof(value) == 'object') { //If it is an array,
+                               dumped_text += level_padding + "'" + item + "' ...\n";
+                               dumped_text += dump(value,level+1);
+                       } else {
+                               dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
+                       }
+               }
+       } else { //Stings/Chars/Numbers etc.
+        dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
+       }
+       return dumped_text;
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/extract_zip/extract_zip.png b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/extract_zip/extract_zip.png
new file mode 100755 (executable)
index 0000000..204a3c5
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/extract_zip/extract_zip.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/extract_zip/plugin.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/extract_zip/plugin.css
new file mode 100644 (file)
index 0000000..aa8ad0a
--- /dev/null
@@ -0,0 +1,4 @@
+.kfm_plugin_extract_zip_contexticon{
+       background-image:url('extract_zip.png');
+       background-repeat:no-repeat;
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/extract_zip/plugin.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/extract_zip/plugin.js
new file mode 100644 (file)
index 0000000..4d9177f
--- /dev/null
@@ -0,0 +1,12 @@
+function plugin_extract_zip(){
+       this.name='extract_zip';
+       this.title=kfm.lang.ExtractZippedFile;
+       this.mode=0; //only one file
+       this.writable=2;
+       this.extensions=['zip'];
+       this.doFunction=function(files){
+               fid=files[0];
+               kfm_extractZippedFile(fid);
+       }
+}
+if(kfm_vars.permissions.file.mk) kfm_addHook(new plugin_extract_zip());
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/file_details/file_details.png b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/file_details/file_details.png
new file mode 100644 (file)
index 0000000..fb92224
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/file_details/file_details.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/file_details/plugin.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/file_details/plugin.css
new file mode 100644 (file)
index 0000000..9d23003
--- /dev/null
@@ -0,0 +1,4 @@
+.kfm_plugin_file_details_contexticon{
+       background-image:url('file_details.png');
+       background-repeat:no-repeat;
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/file_details/plugin.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/file_details/plugin.js
new file mode 100644 (file)
index 0000000..ffc9a8a
--- /dev/null
@@ -0,0 +1,13 @@
+function plugin_file_details(){
+       this.name='file_details',
+       this.title='file details'; // TODO: string
+       this.mode=2;
+       this.writable=2;
+       this.category='returning'; // to put it near the bottom
+       this.extensions=['all'];
+       this.doFunction=function(files){
+               var table=kfm_buildFileDetailsTable(File_getInstance(files[0]));
+               kfm_modal_open(table,'File Details',[]); // TODO: new string
+       }
+}
+kfm_addHook(new plugin_file_details());
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_resize_multiple/plugin.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_resize_multiple/plugin.css
new file mode 100644 (file)
index 0000000..c37ec3f
--- /dev/null
@@ -0,0 +1,4 @@
+.kfm_plugin_image_resize_contexticon{
+       background-image:url('resize_image.png');
+       background-repeat:no-repeat;
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_resize_multiple/plugin.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_resize_multiple/plugin.js
new file mode 100644 (file)
index 0000000..ce6a936
--- /dev/null
@@ -0,0 +1,46 @@
+function plugin_image_resize_multiple(){
+       this.name='image_resize',
+       this.title='Resize Images',
+       this.mode=1;//single files
+       this.writable=1;//writable files
+       this.category='edit';
+       this.extensions=['jpg','png','gif'];
+       this.doFunction=function(files){
+               var id=files[0];
+               var imgs=0,width=0;height=0,imgfiles=[];
+               { // figure out average width/height
+                       for(var i=0;i<files.length;++i){
+                               var data=File_getInstance(files[i]);
+                               if(!data.width || !data.height)continue;
+                               width+=data.width;
+                               height+=data.height;
+                               ++imgs;
+                               imgfiles.push(files[i]);
+                       }
+                       if(!imgs)return;
+                       width=+(width/imgs);
+                       height=+(height/imgs);
+               }
+               var txt=kfm.lang.CurrentSize(width,height);
+               kfm_prompt(txt+kfm.lang.NewWidth,width,function(x){
+                       x=parseInt(x);
+                       if(!x)return;
+                       txt+=kfm.lang.NewWidthConfirmTxt(x);
+                       kfm_prompt(txt+kfm.lang.NewHeight,Math.ceil(height*(x/width)),function(y){
+                               y=parseInt(y);
+                               if(!y)return;
+                               if(kfm.confirm(txt+kfm.lang.NewHeightConfirmTxt(y))){
+                                       kfm_fileLoader(imgfiles);
+                                       x_kfm_resizeImages(imgfiles,x,y,function(){
+                                               imgfiles.each(function(id){
+                                                       var data=File_getInstance(id);
+                                                       x_kfm_getFileDetails(id,File_setData);
+                                                       $j('#kfm_file_icon_'+id).css('background-image','url('+data.icon_url+')');
+                                               });
+                                       });
+                               }
+                       });
+               });
+       }
+}
+if(kfm_vars.permissions.file.ed&&kfm_vars.permissions.image.manip) kfm_addHook(new plugin_image_resize_multiple());
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_resize_multiple/resize_image.png b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_resize_multiple/resize_image.png
new file mode 100644 (file)
index 0000000..c5091dd
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_resize_multiple/resize_image.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_rotate/plugin.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_rotate/plugin.css
new file mode 100644 (file)
index 0000000..3beee06
--- /dev/null
@@ -0,0 +1,8 @@
+.kfm_plugin_rotate_cw_contexticon{
+       background-image:url('rotate_cw.png');
+       background-repeat:no-repeat;
+}
+.kfm_plugin_rotate_ccw_contexticon{
+       background-image:url('rotate_ccw.png');
+       background-repeat:no-repeat;
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_rotate/plugin.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_rotate/plugin.js
new file mode 100644 (file)
index 0000000..821c586
--- /dev/null
@@ -0,0 +1,25 @@
+function plugin_image_rotate(){
+       this.name='rotate',
+       this.title='rotate',
+       this.mode=0;//single files
+       this.writable=1;//writable files
+       this.category='edit';
+       this.extensions=['jpg','png','gif'];
+       this.doFunction=function(){}
+}
+kfm_addHook(new plugin_image_rotate(),{name:'rotate_cw',title:kfm.lang.RotateClockwise,doFunction:function(files){
+               kfm_rotateImage(files[0],270);
+       }
+});
+kfm_addHook(new plugin_image_rotate(),{name:'rotate_ccw',title:kfm.lang.RotateAntiClockwise,doFunction:function(files){
+               kfm_rotateImage(files[0],90);
+       }
+});
+function kfm_rotateImage(id,direction){
+       var F=File_getInstance(id);
+       kfm_fileLoader(id);
+       x_kfm_rotateImage(id,direction,function(id){
+               if($type(id)=='string')return kfm_log(id);
+               F.setThumbnailBackground($('kfm_file_icon_'+id),true);
+       });
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_rotate/rotate_ccw.png b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_rotate/rotate_ccw.png
new file mode 100755 (executable)
index 0000000..cdfdf77
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_rotate/rotate_ccw.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_rotate/rotate_cw.png b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_rotate/rotate_cw.png
new file mode 100755 (executable)
index 0000000..f4aee1e
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/image_rotate/rotate_cw.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer.zip b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer.zip
new file mode 100644 (file)
index 0000000..864bbb1
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer.zip differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/jwplayer.php b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/jwplayer.php
new file mode 100644 (file)
index 0000000..90c1f66
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+require_once('../../initialise.php');
+if(!isset($_GET['id'])) die ('No id given.');
+/*
+$f=kfmFile::getInstance($_GET['id']);
+if(!$f)die('The document with id '.$_GET['id'].' cannot be found');
+$url=$f->getUrl();
+$ext=$f->getExtension();
+*/
+$url='playlist.php?ids='.$_GET['id'];
+print $kfm->doctype;
+?>
+<html>
+<head>
+<title>JW FLV MEDIA PLAYER</title>
+<script type="text/javascript" src="swfobject.js"></script>
+</head>
+<body>
+<div id="media_container"><div id="flashreplace"></div></div>
+<script type="text/javascript">
+var so = new SWFObject('mediaplayer.swf','player','720','260','8');
+so.addParam("allowfullscreen","true");
+so.addParam("allowscriptaccess","always");
+so.addParam("wmode","opaque");
+so.addParam("bgcolor","#000000");
+so.addVariable('file','<?php echo $url;?>');
+so.addVariable('linkfromdisplay','true');
+//so.addVariable('callback','urchin');
+so.addVariable('displaywidth','360');
+so.addVariable('autoscroll','true');
+so.addVariable('lightcolor','0x0099CC');
+so.addVariable("width","720");
+so.addVariable("height","260");
+so.addVariable("autostart",true);
+so.write('flashreplace');
+</script>
+</body>
+</html>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/mediaplayer.swf b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/mediaplayer.swf
new file mode 100755 (executable)
index 0000000..cb103d5
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/mediaplayer.swf differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/playlist.php b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/playlist.php
new file mode 100644 (file)
index 0000000..1061712
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+require_once('../../initialise.php');
+if(!isset($_GET['ids']))die('error: no ids get parameter defined');
+$ids=explode(',',$_GET['ids']);
+header("content-type:text/xml;charset=utf-8");
+echo "<playlist version='1' xmlns='http://xspf.org/ns/0/'>\n";
+echo "<trackList>\n";
+foreach($ids as $id){
+       $f=kfmFile::getInstance($id);
+       if(!$f) continue;
+       echo "\t<track>\n";
+       echo "\t\t<title>".$f->name."</title>\n";
+       echo "\t\t<location>".$f->getUrl()."#.".$f->getExtension()."</location>\n";
+       echo "\t</track>\n";
+}
+echo "</trackList>\n";
+echo "</playlist>\n";
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/plugin.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/plugin.js
new file mode 100644 (file)
index 0000000..4cb9003
--- /dev/null
@@ -0,0 +1,14 @@
+function plugin_jwplayer(){
+       this.name='jwplayer';
+       this.title='Play with JW Media player';
+       this.category='view';
+       this.defaultOpener=1;
+       this.extensions=['flv','jpg','png','gif','svg','mp3'];
+       this.mode=2;
+       this.writable=2;//all
+       this.doFunction=function(files){
+               var url='plugins/jwplayer/jwplayer.php?id='+files.join();
+               kfm_pluginIframeShow(url);
+       }
+}
+kfm_addHook(new plugin_jwplayer());
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/swfobject.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/jwplayer/swfobject.js
new file mode 100755 (executable)
index 0000000..a7f5d69
--- /dev/null
@@ -0,0 +1,8 @@
+/**
+ * SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
+ *
+ * SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ */
+if(typeof deconcept=="undefined"){var deconcept=new Object();}if(typeof deconcept.util=="undefined"){deconcept.util=new Object();}if(typeof deconcept.SWFObjectUtil=="undefined"){deconcept.SWFObjectUtil=new Object();}deconcept.SWFObject=function(_1,id,w,h,_5,c,_7,_8,_9,_a){if(!document.getElementById){return;}this.DETECT_KEY=_a?_a:"detectflash";this.skipDetect=deconcept.util.getRequestParameter(this.DETECT_KEY);this.params=new Object();this.variables=new Object();this.attributes=new Array();if(_1){this.setAttribute("swf",_1);}if(id){this.setAttribute("id",id);}if(w){this.setAttribute("width",w);}if(h){this.setAttribute("height",h);}if(_5){this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));}this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion();if(!window.opera&&document.all&&this.installedVer.major>7){deconcept.SWFObject.doPrepUnload=true;}if(c){this.addParam("bgcolor",c);}var q=_7?_7:"high";this.addParam("quality",q);this.setAttribute("useExpressInstall",false);this.setAttribute("doExpressInstall",false);var _c=(_8)?_8:window.location;this.setAttribute("xiRedirectUrl",_c);this.setAttribute("redirectUrl","");if(_9){this.setAttribute("redirectUrl",_9);}};deconcept.SWFObject.prototype={useExpressInstall:function(_d){this.xiSWFPath=!_d?"expressinstall.swf":_d;this.setAttribute("useExpressInstall",true);},setAttribute:function(_e,_f){this.attributes[_e]=_f;},getAttribute:function(_10){return this.attributes[_10];},addParam:function(_11,_12){this.params[_11]=_12;},getParams:function(){return this.params;},addVariable:function(_13,_14){this.variables[_13]=_14;},getVariable:function(_15){return this.variables[_15];},getVariables:function(){return this.variables;},getVariablePairs:function(){var _16=new Array();var key;var _18=this.getVariables();for(key in _18){_16[_16.length]=key+"="+_18[key];}return _16;},getSWFHTML:function(){var _19="";if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","PlugIn");this.setAttribute("swf",this.xiSWFPath);}_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\"";_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";var _1a=this.getParams();for(var key in _1a){_19+=[key]+"=\""+_1a[key]+"\" ";}var _1c=this.getVariablePairs().join("&");if(_1c.length>0){_19+="flashvars=\""+_1c+"\"";}_19+="/>";}else{if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","ActiveX");this.setAttribute("swf",this.xiSWFPath);}_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\">";_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";var _1d=this.getParams();for(var key in _1d){_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";}var _1f=this.getVariablePairs().join("&");if(_1f.length>0){_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";}_19+="</object>";}return _19;},write:function(_20){if(this.getAttribute("useExpressInstall")){var _21=new deconcept.PlayerVersion([6,0,65]);if(this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version"))){this.setAttribute("doExpressInstall",true);this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));document.title=document.title.slice(0,47)+" - Flash Player Installation";this.addVariable("MMdoctitle",document.title);}}if(this.skipDetect||this.getAttribute("doExpressInstall")||this.installedVer.versionIsValid(this.getAttribute("version"))){var n=(typeof _20=="string")?document.getElementById(_20):_20;n.innerHTML=this.getSWFHTML();return true;}else{if(this.getAttribute("redirectUrl")!=""){document.location.replace(this.getAttribute("redirectUrl"));}}return false;}};deconcept.SWFObjectUtil.getPlayerVersion=function(){var _23=new deconcept.PlayerVersion([0,0,0]);if(navigator.plugins&&navigator.mimeTypes.length){var x=navigator.plugins["Shockwave Flash"];if(x&&x.description){_23=new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));}}else{if(navigator.userAgent&&navigator.userAgent.indexOf("Windows CE")>=0){var axo=1;var _26=3;while(axo){try{_26++;axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_26);_23=new deconcept.PlayerVersion([_26,0,0]);}catch(e){axo=null;}}}else{try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");_23=new deconcept.PlayerVersion([6,0,21]);axo.AllowScriptAccess="always";}catch(e){if(_23.major==6){return _23;}}try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(e){}}if(axo!=null){_23=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));}}}return _23;};deconcept.PlayerVersion=function(_29){this.major=_29[0]!=null?parseInt(_29[0]):0;this.minor=_29[1]!=null?parseInt(_29[1]):0;this.rev=_29[2]!=null?parseInt(_29[2]):0;};deconcept.PlayerVersion.prototype.versionIsValid=function(fv){if(this.major<fv.major){return false;}if(this.major>fv.major){return true;}if(this.minor<fv.minor){return false;}if(this.minor>fv.minor){return true;}if(this.rev<fv.rev){return false;}return true;};deconcept.util={getRequestParameter:function(_2b){var q=document.location.search||document.location.hash;if(_2b==null){return q;}if(q){var _2d=q.substring(1).split("&");for(var i=0;i<_2d.length;i++){if(_2d[i].substring(0,_2d[i].indexOf("="))==_2b){return _2d[i].substring((_2d[i].indexOf("=")+1));}}}return "";}};deconcept.SWFObjectUtil.cleanupSWFs=function(){var _2f=document.getElementsByTagName("OBJECT");for(var i=_2f.length-1;i>=0;i--){_2f[i].style.display="none";for(var x in _2f[i]){if(typeof _2f[i][x]=="function"){_2f[i][x]=function(){};}}}};if(deconcept.SWFObject.doPrepUnload){if(!deconcept.unloadSet){deconcept.SWFObjectUtil.prepUnload=function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};window.attachEvent("onunload",deconcept.SWFObjectUtil.cleanupSWFs);};window.attachEvent("onbeforeunload",deconcept.SWFObjectUtil.prepUnload);deconcept.unloadSet=true;}}if(!document.getElementById&&document.all){document.getElementById=function(id){return document.all[id];};}var getQueryParamValue=deconcept.util.getRequestParameter;var FlashObject=deconcept.SWFObject;var SWFObject=deconcept.SWFObject;
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/lightbox/plugin.css b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/lightbox/plugin.css
new file mode 100644 (file)
index 0000000..0537694
--- /dev/null
@@ -0,0 +1,4 @@
+.kfm_plugin_lightbox_contexticon{
+       background-image:url('slideshow_icon.jpg');
+       background-repeat:no-repeat;
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/lightbox/plugin.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/lightbox/plugin.js
new file mode 100644 (file)
index 0000000..c9c540a
--- /dev/null
@@ -0,0 +1,108 @@
+function plugin_lightbox(){
+       this.name='lightbox';
+       this.title='view slideshow';
+       this.category='view';
+       this.defaultOpener=1;
+       this.extensions=['jpg','png','gif','svg'];
+       this.mode=1;//multiple files
+       this.writable=2;//all
+       this.doFunction=function(files){
+               kfm_img_startLightbox(files);
+       }
+}
+kfm_addHook(new plugin_lightbox());
+kfm_addHook(new plugin_lightbox(),{mode:0,title:kfm.lang.ViewImage});
+function kfm_img_startLightbox(id){
+       window.lightbox_oldCM=$('documents_body').contentMode;
+       $('documents_body').contentMode='lightbox';
+       if(id&&$type(id)=='array'){
+               if(id.length>1){
+                       window.kfm_slideshow={ids:id,at:0};
+                       id=0;
+               }else{
+                       id=id[0];
+               }
+       }
+       if(!id){
+               window.kfm_slideshow.at++;
+               document.title='KFM Slideshow: '+window.kfm_slideshow.at;
+               id=window.kfm_slideshow.ids[window.kfm_slideshow.at%window.kfm_slideshow.ids.length];
+       }
+       var el,data=File_getInstance(id),ws=window.getSize().size,oldEl=$('kfm_lightboxImage'),wrapper=$('kfm_lightboxWrapper');
+       if(!wrapper){
+               wrapper=new Element('div',{
+                       'id':'kfm_lightboxWrapper',
+                       'styles':{
+                               'position':'absolute',
+                               'left':0,
+                               'z-index':1,
+                               'top':0,
+                               'width':ws.x,
+                               'height':ws.y
+                       }
+               });
+               wrapper.addEvent('click',kfm_img_stopLightbox);
+               document.body.appendChild(wrapper);
+               wrapper.focus();
+       }
+       if(!$('kfm_lightboxShader')){
+               el=new Element('div',{
+                       'id':'kfm_lightboxShader',
+                       'styles':{
+                               'width':ws.x,
+                               'height':ws.y,
+                               'background':'#000',
+                               'opacity':'.7'
+                       }
+               });
+               wrapper.appendChild(el);
+       }
+       if(oldEl)oldEl.remove();
+       var w=data.width,h=data.height,url='get.php?id='+id,r=0;
+       if(!w||!h){
+               kfm_log(kfm.lang.NotAnImageOrImageDimensionsNotReported);
+               return kfm_img_stopLightbox();
+       }
+       if(w>ws.x*.9||h>ws.y*.9){
+               if(w>ws.x*.9){
+                       r=.9*ws.x/w;
+                       w*=r;
+                       h*=r;
+               }
+               if(h>ws.y*0.9){
+                       r=.9*ws.y/h;
+                       w*=r;
+                       h*=r;
+               }
+               url+='&width='+parseInt(w)+'&height='+parseInt(h);
+       }
+       el=new Element('img',{
+               'id':'kfm_lightboxImage',
+               'src':url,
+               'styles':{
+                       'position':'absolute',
+                       'left':parseInt((ws.x-w)/2),
+                       'top':parseInt((ws.y-h)/2),
+                       'z-index':2
+               }
+       });
+       if(window.kfm_slideshow&&!window.kfm_slideshow_stopped){
+               el.addEvent('load',function(){
+                       window.lightbox_slideshowTimer=setTimeout('kfm_img_startLightbox()',kfm_slideshow_delay);
+               });
+       }
+       wrapper.appendChild(el);
+       kfm_resizeHandler_add('kfm_lightboxShader');
+       kfm_resizeHandler_add('kfm_lightboxWrapper');
+}
+function kfm_img_stopLightbox(e){
+       e=new Event(e);
+       if(e.rightClick)return;
+       var wrapper=$('kfm_lightboxWrapper');
+       if(wrapper)wrapper.remove();
+       window.kfm_slideshow=window.kfm_slideshow_stopped=null;
+       if(window.lightbox_slideshowTimer)clearTimeout(window.lightbox_slideshowTimer);
+       $('documents_body').contentMode=window.lightbox_oldCM;
+       kfm_resizeHandler_remove('kfm_lightboxShader');
+       kfm_resizeHandler_remove('kfm_lightboxWrapper');
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/lightbox/slideshow_icon.jpg b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/lightbox/slideshow_icon.jpg
new file mode 100644 (file)
index 0000000..fb479af
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/lightbox/slideshow_icon.jpg differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/plugins/return_thumbnail/plugin.js b/ipf/admin/media/tiny_mce/plugins/kfm/plugins/return_thumbnail/plugin.js
new file mode 100644 (file)
index 0000000..e046d6a
--- /dev/null
@@ -0,0 +1,37 @@
+function plugin_return_thumbnail(){
+       this.name='return_thumbnail';
+       this.title=kfm.lang.ReturnThumbnailToOpener;
+       this.mode=0;//single files
+       this.writable=2;//writable files
+       this.category='returning';
+       this.extensions='all';
+       this.doFunction=function(files){
+               kfm_returnThumbnail(files[0]);
+       }
+}
+kfm_addHook(new plugin_return_thumbnail());
+
+function kfm_returnThumbnail(id,size){
+       if(!size)size='64x64';
+       valid=1;
+       kfm_prompt(kfm.lang.WhatMaximumSize,size,function(size){
+               if(!size)return;
+               if(!/^[0-9]+x[0-9]+$/.test(size)){
+                       alert('The size must be in the format XXxYY, where X is the width and Y is the height');
+                       valid=0;
+               }
+               if(!valid)return kfm_returnThumbnail(id,size);
+               var x=size.replace(/x.*/,''),y=size.replace(/.*x/,'');
+               x_kfm_getFileUrl(id,x,y,function(url){
+                       if(kfm_file_handler=='return'||kfm_file_handler=='fckeditor'){
+                               if(copy_to_clipboard)copy_to_clipboard(url);
+                               window.opener.SetUrl(url,0,0,File_getInstance(id).caption);
+                               window.close();
+                       }
+                       else if(kfm_file_handler=='download'){
+                               if(/get.php/.test(url))url+='&forcedownload=1';
+                               document.location=url;
+                       }
+               });
+       });
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.mysql.create.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.mysql.create.php
new file mode 100644 (file)
index 0000000..9914729
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."directories(
+               id INTEGER PRIMARY KEY auto_increment,
+               name text,
+               parent integer not null
+       )DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."files(
+               id INTEGER PRIMARY KEY auto_increment,
+               name text,
+               directory integer not null
+       )DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."files_images(
+               id INTEGER PRIMARY KEY auto_increment,
+               caption text,
+               file_id integer not null,
+               width integer default 0,
+               height integer default 0
+       )DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."files_images_thumbs(
+               id INTEGER PRIMARY KEY auto_increment,
+               image_id integer not null,
+               width integer default 0,
+               height integer default 0
+       )DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."parameters(
+               name text,
+               value text
+       )DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."session (
+               `id` int(11) NOT NULL auto_increment,
+               `cookie` varchar(32) default NULL,
+               `last_accessed` datetime default NULL,
+               PRIMARY KEY  (`id`)
+       ) DEFAULT CHARSET=utf8");
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."session_vars (
+               `session_id` int(11) default NULL,
+               `varname` text,
+               `varvalue` text,
+               KEY `session_id` (`session_id`)
+       ) DEFAULT CHARSET=utf8");
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."tagged_files(
+               file_id INTEGER,
+               tag_id  INTEGER
+       )DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."tags(
+               id INTEGER PRIMARY KEY auto_increment,
+               name text
+       )DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
+
+       $kfmdb->query("insert into ".KFM_DB_PREFIX."parameters values('version','1.3')");
+       $kfmdb->query("insert into ".KFM_DB_PREFIX."directories values(1,'root',0)");
+
+       if(!PEAR::isError($kfmdb))$db_defined=1;
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.mysql.update.0.7.1.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.mysql.update.0.7.1.php
new file mode 100644 (file)
index 0000000..8424b12
--- /dev/null
@@ -0,0 +1,12 @@
+<?php
+       $kfmdb->query('create table tags(
+               id INTEGER PRIMARY KEY auto_increment,
+               name text
+       )');
+       $kfmdb->query('create table tagged_files(
+               file_id INTEGER,
+               tag_id  INTEGER
+       )');
+
+       $kfmdb->query("update parameters set value='0.7.1' where name='version'");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.mysql.update.0.7.2.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.mysql.update.0.7.2.php
new file mode 100644 (file)
index 0000000..35edb2b
--- /dev/null
@@ -0,0 +1,18 @@
+<?php
+       $kfmdb->query("alter table directories rename ".KFM_DB_PREFIX."directories");
+       $kfmdb->query("alter table files rename ".KFM_DB_PREFIX."files");
+       $kfmdb->query("alter table image_captions rename ".KFM_DB_PREFIX."image_captions");
+       $kfmdb->query("alter table ".KFM_DB_PREFIX."image_captions rename ".KFM_DB_PREFIX."files_images");
+       $kfmdb->query("alter table parameters rename ".KFM_DB_PREFIX."parameters");
+       $kfmdb->query("alter table tags rename ".KFM_DB_PREFIX."tags");
+       $kfmdb->query("alter table tagged_files rename ".KFM_DB_PREFIX."tagged_files");
+       $kfmdb->query("alter table ".KFM_DB_PREFIX."files_images add width integer default 0");
+       $kfmdb->query("alter table ".KFM_DB_PREFIX."files_images add height integer default 0");
+       $kfmdb->query("create table ".KFM_DB_PREFIX."files_images_thumbs(
+               id INTEGER PRIMARY KEY auto_increment,
+               image_id integer not null,
+               width integer default 0,
+               height integer default 0
+       )");
+       $kfmdb->query("update ".KFM_DB_PREFIX."parameters set value='0.7.2' where name='version'");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.mysql.update.0.9.1.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.mysql.update.0.9.1.php
new file mode 100644 (file)
index 0000000..74ff4fd
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."directories         DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."directories         DROP physical_address");
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."directories         CHANGE name name text");
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."files               DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."files               CHANGE name name text");
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."files_images        DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."files_images        CHANGE caption caption text");
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."files_images_thumbs DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."parameters          DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."parameters          CHANGE name name text");
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."parameters          CHANGE value value text");
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."tagged_files        DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."tags                DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."tags                CHANGE name name text");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.mysql.update.0.9.2.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.mysql.update.0.9.2.php
new file mode 100644 (file)
index 0000000..f850aaf
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."session (
+               `id` int(11) NOT NULL auto_increment,
+               `cookie` varchar(32) default NULL,
+               `last_accessed` datetime default NULL,
+               PRIMARY KEY  (`id`)
+       ) DEFAULT CHARSET=utf8");
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."session_vars (
+               `session_id` int(11) default NULL,
+               `varname` text,
+               `varvalue` text,
+               KEY `session_id` (`session_id`),
+               CONSTRAINT `".KFM_DB_PREFIX."session_vars_ibfk_1` FOREIGN KEY (`session_id`) REFERENCES `".KFM_DB_PREFIX."session` (`id`)
+       )");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.pgsql.create.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.pgsql.create.php
new file mode 100644 (file)
index 0000000..8f199e5
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+       $kfmdb->query("create table ".KFM_DB_PREFIX."parameters(name text, value text)");
+       $kfmdb->query("create table ".KFM_DB_PREFIX."directories(
+               id serial,
+               name text,
+               parent integer not null,
+               primary key (id)
+       )");
+       $kfmdb->query("create table ".KFM_DB_PREFIX."files(
+               id serial,
+               name text,
+               directory integer not null,
+               primary key (id),
+               foreign key (directory) references ".KFM_DB_PREFIX."directories(id)
+       )");
+       $kfmdb->query("create table ".KFM_DB_PREFIX."files_images(
+               id serial,
+               caption text,
+               file_id integer not null,
+               width integer default 0,
+               height integer default 0,
+               primary key (id),
+               foreign key (file_id) references ".KFM_DB_PREFIX."files(id)
+       )");
+       $kfmdb->query("create table ".KFM_DB_PREFIX."files_images_thumbs(
+               id serial,
+               image_id integer not null,
+               width integer default 0,
+               height integer default 0,
+               primary key (id),
+               foreign key (image_id) references ".KFM_DB_PREFIX."files_images(id)
+       )");
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."session(
+               id serial,
+               cookie varchar(32) default NULL,
+               last_accessed timestamp default NULL,
+               PRIMARY KEY  (id)
+       )");
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."session_vars(
+               session_id integer default NULL,
+               varname text,
+               varvalue text,
+               foreign key (session_id) references ".KFM_DB_PREFIX."session(id)
+       )");
+       $kfmdb->query("create table ".KFM_DB_PREFIX."tags(
+               id serial,
+               name text,
+               primary key (id)
+       )");
+       $kfmdb->query("create table ".KFM_DB_PREFIX."tagged_files(
+               file_id INTEGER,
+               tag_id  INTEGER,
+               foreign key (file_id) references ".KFM_DB_PREFIX."files (id),
+               foreign key (tag_id) references ".KFM_DB_PREFIX."tags (id)
+       )");
+
+       $kfmdb->query("insert into ".KFM_DB_PREFIX."parameters values('version','1.3')");
+       $kfmdb->query("insert into ".KFM_DB_PREFIX."directories values(1,'root',0)");
+       if(!PEAR::isError($kfmdb))$db_defined=1;
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.pgsql.update.0.7.1.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.pgsql.update.0.7.1.php
new file mode 100644 (file)
index 0000000..0a4863a
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+       $kfmdb->query('create table tags(
+               id serial,
+               name text
+               primary key (id)
+       )');
+       $kfmdb->query('create table tagged_files(
+               file_id INTEGER,
+               tag_id  INTEGER,
+               foreign key (file_id) references files (id),
+               foreign key (tag_id) references tags (id)
+       )');
+
+       $kfmdb->query("update parameters set value='0.7.1' where name='version'");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.pgsql.update.0.7.2.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.pgsql.update.0.7.2.php
new file mode 100644 (file)
index 0000000..2713218
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+       $kfmdb->query("alter table directories rename to ".KFM_DB_PREFIX."directories");
+       $kfmdb->query("alter table files rename to ".KFM_DB_PREFIX."files");
+       $kfmdb->query("alter table image_captions rename to ".KFM_DB_PREFIX."image_captions");
+       $kfmdb->query("alter table ".KFM_DB_PREFIX."image_captions rename to ".KFM_DB_PREFIX."files_images");
+       $kfmdb->query("alter table parameters rename to ".KFM_DB_PREFIX."parameters");
+       $kfmdb->query("alter table tags rename to ".KFM_DB_PREFIX."tags");
+       $kfmdb->query("alter table tagged_files rename to ".KFM_DB_PREFIX."tagged_files");
+       $kfmdb->query("alter table ".KFM_DB_PREFIX."files_images add width integer default 0");
+       $kfmdb->query("alter table ".KFM_DB_PREFIX."files_images add height integer default 0");
+       $kfmdb->query("create table ".KFM_DB_PREFIX."files_images_thumbs(
+               id serial,
+               image_id integer not null,
+               width integer default 0,
+               height integer default 0,
+               primary key (id),
+               foreign key (image_id) references ".KFM_DB_PREFIX."files_images(id)
+       )");
+       $kfmdb->query("update ".KFM_DB_PREFIX."parameters set value='0.7.2' where name='version'");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.pgsql.update.0.9.1.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.pgsql.update.0.9.1.php
new file mode 100644 (file)
index 0000000..abb1f0a
--- /dev/null
@@ -0,0 +1,3 @@
+<?php
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."directories DROP physical_address");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.pgsql.update.0.9.2.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.pgsql.update.0.9.2.php
new file mode 100644 (file)
index 0000000..0363308
--- /dev/null
@@ -0,0 +1,14 @@
+<?php
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."session(
+               id serial,
+               cookie varchar(32) default NULL,
+               last_accessed timestamp default NULL,
+               PRIMARY KEY  (id)
+       )");
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."session_vars(
+               session_id integer default NULL,
+               varname text,
+               varvalue text,
+               foreign key (session_id) references ".KFM_DB_PREFIX."session(id)
+       )");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.sqlite.create.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.sqlite.create.php
new file mode 100644 (file)
index 0000000..a1d8d1f
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+       $kfmdb->query("create table ".KFM_DB_PREFIX."directories(
+               id INTEGER PRIMARY KEY,
+               name text,
+               parent integer not null
+       )");
+       $kfmdb->query("create table ".KFM_DB_PREFIX."files(
+               id INTEGER PRIMARY KEY,
+               name text,
+               directory integer not null,
+               foreign key (directory) references ".KFM_DB_PREFIX."directories(id)
+       )");
+       $kfmdb->query("create table ".KFM_DB_PREFIX."files_images(
+               id INTEGER PRIMARY KEY,
+               caption text,
+               file_id integer not null,
+               width integer default 0,
+               height integer default 0,
+               foreign key (file_id) references ".KFM_DB_PREFIX."files(id)
+       )");
+       $kfmdb->query("create table ".KFM_DB_PREFIX."files_images_thumbs(
+               id INTEGER PRIMARY KEY,
+               image_id integer not null,
+               width integer default 0,
+               height integer default 0,
+               foreign key (image_id) references ".KFM_DB_PREFIX."files_images(id)
+       )");
+       $kfmdb->query("create table ".KFM_DB_PREFIX."parameters(name text, value text)");
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."session (
+               id INTEGER PRIMARY KEY,
+               cookie varchar(32) default NULL,
+               last_accessed datetime default NULL
+       )");
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."session_vars (
+               session_id INTEGER,
+               varname text,
+               varvalue text,
+               FOREIGN KEY (session_id) REFERENCES ".KFM_DB_PREFIX."session (id)
+       )");
+       $kfmdb->query("create table ".KFM_DB_PREFIX."tags(
+               id INTEGER PRIMARY KEY,
+               name text
+       )");
+       $kfmdb->query("create table ".KFM_DB_PREFIX."tagged_files(
+               file_id INTEGER,
+               tag_id  INTEGER,
+               foreign key(file_id) references ".KFM_DB_PREFIX."files(id),
+               foreign key(tag_id) references ".KFM_DB_PREFIX."tags(id)
+       )");
+
+       $kfmdb->query("insert into ".KFM_DB_PREFIX."parameters values('version','1.3')");
+       $kfmdb->query("insert into ".KFM_DB_PREFIX."directories values(1,'root',0)");
+       $db_defined=1;
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.sqlite.update.0.7.1.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.sqlite.update.0.7.1.php
new file mode 100644 (file)
index 0000000..c21307e
--- /dev/null
@@ -0,0 +1,14 @@
+<?php
+       $kfmdb->query('create table tags(
+               id INTEGER PRIMARY KEY,
+               name text
+       )');
+       $kfmdb->query('create table tagged_files(
+               file_id INTEGER,
+               tag_id  INTEGER,
+               foreign key(file_id) references files(id),
+               foreign key(tag_id) references tags(id)
+       )');
+
+       $kfmdb->query("update parameters set value='0.7.1' where name='version'");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.sqlite.update.0.7.2.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.sqlite.update.0.7.2.php
new file mode 100644 (file)
index 0000000..8577a5f
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+       $kfmdb->query("alter table directories rename to ".KFM_DB_PREFIX."directories");
+       $kfmdb->query("alter table files rename to ".KFM_DB_PREFIX."files");
+       $kfmdb->query("alter table image_captions rename to ".KFM_DB_PREFIX."image_captions");
+       $kfmdb->query("alter table ".KFM_DB_PREFIX."image_captions rename to ".KFM_DB_PREFIX."files_images");
+       $kfmdb->query("alter table parameters rename to ".KFM_DB_PREFIX."parameters");
+       $kfmdb->query("alter table tags rename to ".KFM_DB_PREFIX."tags");
+       $kfmdb->query("alter table tagged_files rename to ".KFM_DB_PREFIX."tagged_files");
+       $kfmdb->query("alter table ".KFM_DB_PREFIX."files_images add width integer default 0");
+       $kfmdb->query("alter table ".KFM_DB_PREFIX."files_images add height integer default 0");
+       $kfmdb->query("create table ".KFM_DB_PREFIX."files_images_thumbs(
+               id INTEGER PRIMARY KEY,
+               image_id integer not null,
+               width integer default 0,
+               height integer default 0,
+               foreign key (image_id) references ".KFM_DB_PREFIX."files_images(id)
+       )");
+       $kfmdb->query("update ".KFM_DB_PREFIX."parameters set value='0.7.2' where name='version'");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.sqlite.update.0.9.1.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.sqlite.update.0.9.1.php
new file mode 100644 (file)
index 0000000..abb1f0a
--- /dev/null
@@ -0,0 +1,3 @@
+<?php
+       $kfmdb->query("ALTER TABLE ".KFM_DB_PREFIX."directories DROP physical_address");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.sqlite.update.0.9.2.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/db.sqlite.update.0.9.2.php
new file mode 100644 (file)
index 0000000..0ec6276
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."session (
+               `id` int(11) NOT NULL auto_increment,
+               `cookie` varchar(32) default NULL,
+               `last_accessed` datetime default NULL,
+               PRIMARY KEY  (`id`)
+       )");
+       $kfmdb->query("CREATE TABLE ".KFM_DB_PREFIX."session_vars (
+               `session_id` int(11) default NULL,
+               `varname` text,
+               `varvalue` text,
+               KEY `session_id` (`session_id`),
+               CONSTRAINT `".KFM_DB_PREFIX."session_vars_ibfk_1` FOREIGN KEY (`session_id`) REFERENCES `".KFM_DB_PREFIX."session` (`id`)
+       )");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/image_resize/plugin.css b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/image_resize/plugin.css
new file mode 100644 (file)
index 0000000..c37ec3f
--- /dev/null
@@ -0,0 +1,4 @@
+.kfm_plugin_image_resize_contexticon{
+       background-image:url('resize_image.png');
+       background-repeat:no-repeat;
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/image_resize/plugin.js b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/image_resize/plugin.js
new file mode 100644 (file)
index 0000000..dd048ad
--- /dev/null
@@ -0,0 +1,31 @@
+function plugin_image_resize(){
+       this.name='image_resize',
+       this.title=kfm.lang.ResizeImage,
+       this.mode=0;//single files
+       this.writable=1;//writable files
+       this.category='edit';
+       this.extensions=['jpg','png','gif'];
+       this.doFunction=function(files){
+               var id=files[0];
+               var data=File_getInstance(id);
+               var txt=kfm.lang.CurrentSize(data.width,data.height);
+               kfm_prompt(txt+kfm.lang.NewWidth,data.width,function(x){
+                       x=parseInt(x);
+                       if(!x)return;
+                       txt+=kfm.lang.NewWidthConfirmTxt(x);
+                       kfm_prompt(txt+kfm.lang.NewHeight,Math.ceil(data.height*(x/data.width)),function(y){
+                               y=parseInt(y);
+                               if(!y)return;
+                               if(kfm.confirm(txt+kfm.lang.NewHeightConfirmTxt(y))){
+                                       kfm_fileLoader(id);
+                                       //x_kfm_resizeImage(id,x,y,kfm_refreshFiles);
+                                       x_kfm_resizeImage(id,x,y,function(){
+                                               x_kfm_getFileDetails(id,File_setData);
+                                               $j('#kfm_file_icon_'+data.id).css('background-image','url('+data.icon_url+')');
+                                       });
+                               }
+                       });
+               });
+       }
+}
+if(kfm_vars.permissions.file.ed&&kfm_vars.permissions.image.manip) kfm_addHook(new plugin_image_resize());
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/image_resize/resize_image.png b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/image_resize/resize_image.png
new file mode 100644 (file)
index 0000000..c5091dd
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/image_resize/resize_image.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.0.7.1.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.0.7.1.php
new file mode 100644 (file)
index 0000000..f1eedfe
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+switch($kfm_db_type){
+       case 'mysql':{
+               require 'scripts/db.mysql.update.0.7.1.php';
+               break;
+       }
+       case 'pgsql':{
+               require 'scripts/db.pgsql.update.0.7.1.php';
+               break;
+       }
+       case 'sqlite':{
+               require 'scripts/db.sqlite.update.0.7.1.php';
+               break;
+       }
+       default:{
+               echo 'error: unknown database specified in scripts/update.0.7.1.php';
+               exit;
+       }
+}
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.0.7.2.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.0.7.2.php
new file mode 100644 (file)
index 0000000..ef238a8
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+if($version==''||$version=='7.0'||$version<'0.7.1')require 'scripts/update.0.7.1.php';
+switch($kfm_db_type){
+       case 'mysql':{
+               require 'scripts/db.mysql.update.0.7.2.php';
+               break;
+       }
+       case 'pgsql':{
+               require 'scripts/db.pgsql.update.0.7.2.php';
+               break;
+       }
+       case 'sqlite':{
+               require 'scripts/db.sqlite.update.0.7.2.php';
+               break;
+       }
+       default:{
+               echo 'error: unknown database specified in scripts/update.0.7.2.php';
+               exit;
+       }
+}
+echo '<em>Your database has been updated. Please reload this window.</em>';
+exit;
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.0.8.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.0.8.php
new file mode 100644 (file)
index 0000000..901887b
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+if($version==''||$version=='7.0'||$version<'0.7.2')require 'scripts/update.0.7.2.php';
+switch($kfm_db_type){
+       case 'mysql':{
+               require 'scripts/db.mysql.update.0.7.2.php';
+               break;
+       }
+       case 'pgsql':{
+               require 'scripts/db.pgsql.update.0.7.2.php';
+               break;
+       }
+       case 'sqlite':{
+               require 'scripts/db.sqlite.update.0.7.2.php';
+               break;
+       }
+       default:{
+               echo 'error: unknown database specified in scripts/update.0.7.2.php';
+               exit;
+       }
+}
+$kfmdb->query("delete from ".KFM_DB_PREFIX."parameters where name='version'");
+$kfmdb->query("insert into ".KFM_DB_PREFIX."parameters set value='0.8',name='version'");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.0.9.1.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.0.9.1.php
new file mode 100644 (file)
index 0000000..5369461
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+$version=$kfm_parameters['version'];
+if($version==''||$version=='7.0'||$version<'0.9.1')require 'scripts/update.0.8.php';
+switch($kfm_db_type){
+       case 'mysql':{
+               require 'scripts/db.mysql.update.0.9.1.php';
+               break;
+       }
+       case 'pgsql':{
+               require 'scripts/db.pgsql.update.0.9.1.php';
+               break;
+       }
+       case 'sqlite':{
+               require 'scripts/db.sqlite.update.0.9.1.php';
+               break;
+       }
+       default:{
+               echo 'error: unknown database specified in scripts/update.0.9.1.php';
+               exit;
+       }
+}
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.0.9.2.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.0.9.2.php
new file mode 100644 (file)
index 0000000..b9240ab
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+$version=$kfm_parameters['version'];
+if($version==''||$version=='7.0'||$version<'0.9.2')require 'scripts/update.0.9.1.php';
+switch($kfm_db_type){
+       case 'mysql':{
+               require 'scripts/db.mysql.update.0.9.2.php';
+               break;
+       }
+       case 'pgsql':{
+               require 'scripts/db.pgsql.update.0.9.2.php';
+               break;
+       }
+       case 'sqlite':{
+               require 'scripts/db.sqlite.update.0.9.2.php';
+               break;
+       }
+       default:{
+               echo 'error: unknown database specified in scripts/update.0.9.2.php';
+               exit;
+       }
+}
+$kfm_parameters['version']='0.9.2';
+$kfmdb->query("delete from ".KFM_DB_PREFIX."parameters where name='version'");
+$kfmdb->query("insert into ".KFM_DB_PREFIX."parameters (name,value) values ('version','0.9.2')");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.1.0.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.1.0.php
new file mode 100644 (file)
index 0000000..0edbaf0
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+$version=$kfm_parameters['version'];
+if($version==''||$version=='7.0'||$version<'0.9.2')require 'scripts/update.0.9.2.php';
+$kfm_parameters['version']='1.0';
+$kfmdb->query("delete from ".KFM_DB_PREFIX."parameters where name='version'");
+$kfmdb->query("insert into ".KFM_DB_PREFIX."parameters (name,value) values ('version','1.0')");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.1.1.1.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.1.1.1.php
new file mode 100644 (file)
index 0000000..3c63dc8
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+$version=$kfm_parameters['version'];
+if($version==''||$version=='7.0'||$version<'1.1.1')require KFM_BASE_PATH.'scripts/update.1.1.php';
+$kfm_parameters['version']='1.1.1';
+$kfmdb->query("delete from ".KFM_DB_PREFIX."parameters where name='version'");
+$kfmdb->query("insert into ".KFM_DB_PREFIX."parameters (name,value) values ('version','".$kfm_parameters['version']."')");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.1.1.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.1.1.php
new file mode 100644 (file)
index 0000000..729ec29
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+$version=$kfm_parameters['version'];
+if($version==''||$version=='7.0'||$version<'1.0')require KFM_BASE_PATH.'scripts/update.1.0.php';
+$kfm_parameters['version']='1.1';
+$kfmdb->query("delete from ".KFM_DB_PREFIX."parameters where name='version'");
+$kfmdb->query("insert into ".KFM_DB_PREFIX."parameters (name,value) values ('version','".$kfm_parameters['version']."')");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.1.2.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.1.2.php
new file mode 100644 (file)
index 0000000..c4c0465
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+$version=$kfm_parameters['version'];
+if($version==''||$version=='7.0'||$version<'1.2')require KFM_BASE_PATH.'scripts/update.1.1.1.php';
+$kfm_parameters['version']='1.2';
+$kfmdb->query("delete from ".KFM_DB_PREFIX."parameters where name='version'");
+$kfmdb->query("insert into ".KFM_DB_PREFIX."parameters (name,value) values ('version','".$kfm_parameters['version']."')");
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.1.3.php b/ipf/admin/media/tiny_mce/plugins/kfm/scripts/update.1.3.php
new file mode 100644 (file)
index 0000000..28e1c75
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+$version=$kfm_parameters['version'];
+if($version==''||$version=='7.0'||$version<'1.3')require KFM_BASE_PATH.'scripts/update.1.2.php';
+$kfm_parameters['version']='1.3';
+$kfmdb->query('update '.KFM_DB_PREFIX.'directories set name="root" where id=1');
+$kfmdb->query('update '.KFM_DB_PREFIX.'parameters set value="'.$kfm_parameters['version'].'" where name="version"');
+?>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/.htaccess b/ipf/admin/media/tiny_mce/plugins/kfm/themes/.htaccess
new file mode 100644 (file)
index 0000000..4439849
--- /dev/null
@@ -0,0 +1,4 @@
+<IfModule mod_expires.c>
+       ExpiresActive On
+       ExpiresDefault "access plus 52 weeks"
+</IfModule>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/bitsandpieces/panelheader-bg.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/bitsandpieces/panelheader-bg.png
new file mode 100644 (file)
index 0000000..14b0993
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/bitsandpieces/panelheader-bg.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/bitsandpieces/panelheader.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/bitsandpieces/panelheader.png
new file mode 100644 (file)
index 0000000..4509ff2
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/bitsandpieces/panelheader.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/css.php b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/css.php
new file mode 100644 (file)
index 0000000..0ca3b2d
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+$css=file_get_contents('kfm.css');
+$css.=file_get_contents('hooks.css');
+$css.=file_get_contents('prompt.css');
+header('Content-type: text/css');
+//header('Expires: '.gmdate("D, d M Y H:i:s", time() + 3600*24*365).' GMT');
+echo $css;
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/folders.gif b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/folders.gif
new file mode 100644 (file)
index 0000000..54de8f5
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/folders.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/hooks.css b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/hooks.css
new file mode 100644 (file)
index 0000000..59e8087
--- /dev/null
@@ -0,0 +1,26 @@
+.kfm_plugin_default_contexticon{
+       background-color:#eee;
+       border:1px solid #ddd;
+}
+.kfm_plugin_image_resize_contexticon{
+
+}
+.kfm_plugin_download_contexticon{
+       background-image:url(icons/downloadicon.gif);
+       background-repeat:no-repeat;
+}
+.kfm_plugin_remove_contexticon{
+       background-image:url(icons/remove.png);
+       background-repeat:no-repeat;
+}
+.kfm_plugin_iframe_button{
+       margin-left:10px;
+       cursor:pointer;
+       border-style:outset;
+       border-color:#eee;
+       border-width:2px;
+}
+.kfm_plugin_iframe_button:hover{
+       background-color:white;
+       color:black;
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/actions/1rightarrow.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/actions/1rightarrow.png
new file mode 100644 (file)
index 0000000..c2673b1
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/actions/1rightarrow.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/aac.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/aac.png
new file mode 100755 (executable)
index 0000000..a284752
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/aac.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/aac2.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/aac2.png
new file mode 100755 (executable)
index 0000000..d92d958
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/aac2.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ape.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ape.png
new file mode 100755 (executable)
index 0000000..9194497
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ape.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/avi.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/avi.png
new file mode 100755 (executable)
index 0000000..6fab637
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/avi.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/avi2.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/avi2.png
new file mode 100755 (executable)
index 0000000..8415fde
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/avi2.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/bz2.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/bz2.png
new file mode 100755 (executable)
index 0000000..c3a8989
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/bz2.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/chm.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/chm.png
new file mode 100755 (executable)
index 0000000..14b44ab
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/chm.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/core.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/core.png
new file mode 100755 (executable)
index 0000000..3a9d4e5
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/core.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/deb.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/deb.png
new file mode 100755 (executable)
index 0000000..9cc8b4e
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/deb.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/doc.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/doc.png
new file mode 100755 (executable)
index 0000000..2e30a09
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/doc.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/document.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/document.png
new file mode 100755 (executable)
index 0000000..80551fa
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/document.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/empty.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/empty.png
new file mode 100755 (executable)
index 0000000..d49d6ee
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/empty.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/flac.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/flac.png
new file mode 100755 (executable)
index 0000000..6096571
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/flac.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/folder_setting.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/folder_setting.png
new file mode 100755 (executable)
index 0000000..59773bb
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/folder_setting.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/font.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/font.png
new file mode 100755 (executable)
index 0000000..086898c
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/font.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/font_truetype.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/font_truetype.png
new file mode 100755 (executable)
index 0000000..0c1db4a
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/font_truetype.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/gz.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/gz.png
new file mode 100755 (executable)
index 0000000..59ac500
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/gz.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/html.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/html.png
new file mode 100755 (executable)
index 0000000..1855069
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/html.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/mov.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/mov.png
new file mode 100755 (executable)
index 0000000..98696cc
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/mov.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/mp3.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/mp3.png
new file mode 100755 (executable)
index 0000000..955def8
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/mp3.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/mp4.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/mp4.png
new file mode 100755 (executable)
index 0000000..52606b2
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/mp4.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/odt.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/odt.png
new file mode 100755 (executable)
index 0000000..afed4c6
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/odt.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ogg.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ogg.png
new file mode 100755 (executable)
index 0000000..942bdc8
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ogg.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/pdf.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/pdf.png
new file mode 100755 (executable)
index 0000000..4fac037
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/pdf.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/php.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/php.png
new file mode 100755 (executable)
index 0000000..9a80139
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/php.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ppt.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ppt.png
new file mode 100755 (executable)
index 0000000..2ea1ec3
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ppt.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/qt.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/qt.png
new file mode 100755 (executable)
index 0000000..eda23ca
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/qt.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ram.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ram.png
new file mode 100755 (executable)
index 0000000..4f0a50c
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ram.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rar.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rar.png
new file mode 100755 (executable)
index 0000000..61af807
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rar.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rm.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rm.png
new file mode 100755 (executable)
index 0000000..9b6d661
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rm.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rmvb.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rmvb.png
new file mode 100755 (executable)
index 0000000..112cb79
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rmvb.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rpm.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rpm.png
new file mode 100755 (executable)
index 0000000..918845c
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rpm.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rt.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rt.png
new file mode 100755 (executable)
index 0000000..7881dea
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rt.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rtf.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rtf.png
new file mode 100755 (executable)
index 0000000..a32789a
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rtf.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ruby.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ruby.png
new file mode 100755 (executable)
index 0000000..04b1582
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/ruby.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rv.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rv.png
new file mode 100755 (executable)
index 0000000..ffc7eb8
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/rv.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/svg.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/svg.png
new file mode 100755 (executable)
index 0000000..80c2ea4
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/svg.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/sxw.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/sxw.png
new file mode 100755 (executable)
index 0000000..de9b3a0
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/sxw.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/tar.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/tar.png
new file mode 100755 (executable)
index 0000000..20bba50
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/tar.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/tgz.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/tgz.png
new file mode 100755 (executable)
index 0000000..39718cd
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/tgz.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/txt.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/txt.png
new file mode 100755 (executable)
index 0000000..1a94cfb
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/txt.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/txt2.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/txt2.png
new file mode 100755 (executable)
index 0000000..f23b0a7
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/txt2.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/unknown.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/unknown.png
new file mode 100755 (executable)
index 0000000..d49d6ee
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/unknown.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/xls.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/xls.png
new file mode 100755 (executable)
index 0000000..62f5e6c
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/xls.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/zip.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/zip.png
new file mode 100755 (executable)
index 0000000..0079f2d
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/16x16/mimetypes/zip.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/loader.gif b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/loader.gif
new file mode 100644 (file)
index 0000000..1b19b3b
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/loader.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/aac.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/aac.png
new file mode 100644 (file)
index 0000000..0eb2c23
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/aac.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/aac2.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/aac2.png
new file mode 100644 (file)
index 0000000..bf7bcb0
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/aac2.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ape.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ape.png
new file mode 100644 (file)
index 0000000..7a9ed91
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ape.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/avi.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/avi.png
new file mode 100644 (file)
index 0000000..f22ba1b
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/avi.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/avi2.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/avi2.png
new file mode 100644 (file)
index 0000000..c181cf9
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/avi2.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/bz2.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/bz2.png
new file mode 100644 (file)
index 0000000..84e4060
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/bz2.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/chm.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/chm.png
new file mode 100644 (file)
index 0000000..13e28f2
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/chm.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/core.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/core.png
new file mode 100644 (file)
index 0000000..ba9f196
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/core.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/deb.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/deb.png
new file mode 100644 (file)
index 0000000..468ecdc
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/deb.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/doc.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/doc.png
new file mode 100644 (file)
index 0000000..b0564c4
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/doc.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/document.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/document.png
new file mode 100644 (file)
index 0000000..d67e260
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/document.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/empty.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/empty.png
new file mode 100644 (file)
index 0000000..3cb2363
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/empty.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/flac.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/flac.png
new file mode 100644 (file)
index 0000000..05f44fe
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/flac.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/folder_setting.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/folder_setting.png
new file mode 100644 (file)
index 0000000..a6e4955
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/folder_setting.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/font.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/font.png
new file mode 100644 (file)
index 0000000..f419dff
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/font.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/font_truetype.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/font_truetype.png
new file mode 100644 (file)
index 0000000..a2b017f
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/font_truetype.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/gz.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/gz.png
new file mode 100644 (file)
index 0000000..229891e
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/gz.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/html.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/html.png
new file mode 100644 (file)
index 0000000..6265f4a
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/html.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/mov.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/mov.png
new file mode 100644 (file)
index 0000000..950bc5f
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/mov.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/mp3.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/mp3.png
new file mode 100644 (file)
index 0000000..6a89239
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/mp3.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/mp4.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/mp4.png
new file mode 100644 (file)
index 0000000..a1c1f6d
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/mp4.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/odt.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/odt.png
new file mode 100644 (file)
index 0000000..4b0a87e
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/odt.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ogg.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ogg.png
new file mode 100644 (file)
index 0000000..de0cf26
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ogg.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/pdf.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/pdf.png
new file mode 100644 (file)
index 0000000..3653fc4
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/pdf.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/php.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/php.png
new file mode 100644 (file)
index 0000000..a437dec
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/php.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/qt.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/qt.png
new file mode 100644 (file)
index 0000000..18ac965
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/qt.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ram.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ram.png
new file mode 100644 (file)
index 0000000..11e5b44
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ram.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rar.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rar.png
new file mode 100644 (file)
index 0000000..682ed76
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rar.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rm.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rm.png
new file mode 100644 (file)
index 0000000..5409e8f
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rm.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rmvb.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rmvb.png
new file mode 100644 (file)
index 0000000..371b10d
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rmvb.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rpm.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rpm.png
new file mode 100644 (file)
index 0000000..f3af28c
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rpm.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rt.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rt.png
new file mode 100644 (file)
index 0000000..49609c2
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rt.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rtf.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rtf.png
new file mode 100644 (file)
index 0000000..04bdc37
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rtf.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ruby.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ruby.png
new file mode 100644 (file)
index 0000000..35c37c8
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/ruby.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rv.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rv.png
new file mode 100644 (file)
index 0000000..09dcf72
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/rv.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/svg.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/svg.png
new file mode 100644 (file)
index 0000000..f9f6e5b
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/svg.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/sxw.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/sxw.png
new file mode 100644 (file)
index 0000000..6c06e8f
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/sxw.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/tar.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/tar.png
new file mode 100644 (file)
index 0000000..72307f4
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/tar.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/tgz.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/tgz.png
new file mode 100644 (file)
index 0000000..be78e5f
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/tgz.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/txt.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/txt.png
new file mode 100644 (file)
index 0000000..f6669d7
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/txt.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/txt2.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/txt2.png
new file mode 100644 (file)
index 0000000..2229076
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/txt2.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/unknown.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/unknown.png
new file mode 100644 (file)
index 0000000..3cb2363
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/unknown.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/xls.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/xls.png
new file mode 100644 (file)
index 0000000..23070a1
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/xls.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/zip.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/zip.png
new file mode 100644 (file)
index 0000000..c2b52ba
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/64x64/mimetypes/zip.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/add_tags.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/add_tags.png
new file mode 100755 (executable)
index 0000000..5145507
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/add_tags.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/ark_selectall.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/ark_selectall.png
new file mode 100755 (executable)
index 0000000..25f6a4d
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/ark_selectall.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/downloadicon.gif b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/downloadicon.gif
new file mode 100755 (executable)
index 0000000..69dc04c
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/downloadicon.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/edit.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/edit.png
new file mode 100755 (executable)
index 0000000..cd77c30
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/edit.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/extract_zip.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/extract_zip.png
new file mode 100755 (executable)
index 0000000..204a3c5
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/extract_zip.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/filenew.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/filenew.png
new file mode 100755 (executable)
index 0000000..bfe1d06
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/filenew.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/folder.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/folder.png
new file mode 100755 (executable)
index 0000000..94e7c23
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/folder.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/folder_new.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/folder_new.png
new file mode 100755 (executable)
index 0000000..130e35e
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/folder_new.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/folder_yellow.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/folder_yellow.png
new file mode 100755 (executable)
index 0000000..d15f271
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/folder_yellow.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/invert_selection.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/invert_selection.png
new file mode 100755 (executable)
index 0000000..4005f67
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/invert_selection.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/lock.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/lock.png
new file mode 100755 (executable)
index 0000000..5294896
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/lock.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/remove.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/remove.png
new file mode 100755 (executable)
index 0000000..e188886
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/remove.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/resize_image.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/resize_image.png
new file mode 100644 (file)
index 0000000..c5091dd
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/resize_image.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/rotate_ccw.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/rotate_ccw.png
new file mode 100755 (executable)
index 0000000..cdfdf77
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/rotate_ccw.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/rotate_cw.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/rotate_cw.png
new file mode 100755 (executable)
index 0000000..f4aee1e
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/rotate_cw.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/select_none.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/select_none.png
new file mode 100755 (executable)
index 0000000..1cb0daa
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/select_none.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/show_panel.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/show_panel.png
new file mode 100755 (executable)
index 0000000..abe0f66
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/show_panel.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/unlock.png b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/unlock.png
new file mode 100755 (executable)
index 0000000..3a1a0d3
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/icons/unlock.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/kfm.css b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/kfm.css
new file mode 100755 (executable)
index 0000000..0305462
--- /dev/null
@@ -0,0 +1,220 @@
+*{font-size:8pt;font-family:"Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif;text-align:left;}
+h1,h2{font-weight:bold;padding:0}
+h1{font-size:14px;background:#fff;border-bottom:1px solid #666;margin:0}
+h2{font-size:12px;font-style:italic;border:solid #ccc;background:#ddd;border-width:1px 0 1px;margin:5px 0}
+html{height:100%} /* solves a bug in Konqueror */
+body{margin:0;padding:0;height:100%}
+form{padding:0;margin:0}
+strong{font-weight:bold}
+td{vertical-align:top}
+
+a{color:#006A95;}
+a:hover { color: #036; }
+
+.viewselector{
+       float:right;
+}
+
+#kdnd_drag_wrapper{
+       border:1px solid #ccc;background:#eee
+}
+
+#formWrapper{background:url('bitsandpieces/panelheader-bg.png') repeat-x #eee;border:1px solid #aaa; padding-bottom:5px;}
+#formWrapper h2.prompt{padding:0 5px;position:relative;font-size:12px;line-height:23px;height:23px;margin:0;}
+#formWrapper input,#formwrapper textarea{min-width:200px; width:300px;}
+#formWrapper .button{float:right;border:1px solid;border-color:#ccc #666 #666 #ccc;display:block;background:#ddd;color:#000;text-decoration:none;margin:2;padding:0 5px}
+
+#kfm_directories .kfm_dir_name.kfm_directory_open{background:url(folders.gif) -48px -18px no-repeat #fe9}
+#kfm_directory_properties{color:#666}
+#kfm_directory_properties strong{display:block;font-weight:bold;border:solid #bababa;border-width:0 1px 1px 0}
+#kfm_drag_wrapper{position:absolute;padding:10px;color:#00f;border:1px solid #000;-moz-border-radius:10px;font-size:smaller;background:#eee;opacity:.7}
+#kfm_drag_wrapper i{font-style:italic;text-decoration:none;color:#666}
+#kfm_drag_wrapper.directory{padding:0 0 0 16px;-moz-border-radius:0;min-width:120px;background:url(folders.gif) no-repeat -48px 0 #fff;}
+#kfm_selection_drag_wrapper{position:absolute;border:1px solid #000;-moz-border-radius:10px}
+#kfm_left_column{width:240px;position:relative;float:left;background:white;border-right:1px solid #bababa;overflow:hidden}
+#kfm_logs_panel p{border-top:1px solid #bababa;font:10px sans-serif;margin:0;padding:0;color:#666}
+#kfm_logs_panel p:first-child{border:none}
+#kfm_right_column{overflow:hidden;position:relative;height:100%;background:white}
+#kfm_right_column div.kfm_panel_header{background:url(bitsandpieces/panelheader-bg.png) repeat-x}
+#kfm_right_column #kfm_editFileTable textarea{background:#eee;font-style:italic}
+#kfm_right_column #kfm_editFileTable td{text-align:center}
+#kfm_search_table{width:90%}
+#kfm_search_table td{padding:5px;}
+#kfm_search{width:100%}
+#kfm_tooltip{border:1px solid #000;background:#eee}
+#documents_body{position:relative;overflow:auto;width:100%;height:97%;}
+
+.boxdroptracer{border:1px solid #000;-moz-border-radius:10px;background:#9cf;height:0;width:0;position:absolute;left:0;top:0}
+
+.contextmenu{width:auto;margin:0;padding:0;position:absolute;background:#fff;border:1px solid #000}
+.contextmenu tr .kfm_contextmenu_nameCell:hover{background-color:#efefde;}
+.contextmenu a{display:block;color:#000;text-decoration:none}
+.contextmenu tr.disabled *{color:#ccc;}
+.contextmenu .kfm_contextmenu_iconCell{width:20px;height:20px}
+.contextmenu .is_submenu .kfm_contextmenu_nameCell{font-style:italic;font-weight:bold;padding-right:16px;background:url(icons/16x16/actions/1rightarrow.png) right center no-repeat}
+
+div.kfm_panel{position:relative;width:240px;background:url(bitsandpieces/panelheader-bg.png) repeat-x}
+div.kfm_panel_body{width:240px;overflow:auto;position:relative}
+#kfm_file_upload_panel div.kfm_panel_body{overflow:hidden; padding:5px;}
+div.kfm_panel_header{padding:0 5px;position:relative;font-size:8pt; font-weight:bold; line-height:23px;height:23px}
+#left_column div.kfm_panel_header{width:240px}
+html>body #left_column div.kfm_panel_header{width:230px}
+div.kfm_panel_header a{font-size:0;text-indent:-4000px;position:absolute;height:23px;width:20px;background-image:url(bitsandpieces/panelheader.png);top:0}
+div.kfm_panel_header a.kfm_panel_header_x{right:0;background-position:-102px 0}
+div.kfm_panel_header a.kfm_panel_header_x:hover{right:0;background-position:-102px -46px}
+div.kfm_panel_header a.kfm_panel_header_M{right:21px;background-position:-81px 0}
+div.kfm_panel_header a.kfm_panel_header_M:hover{right:21px;background-position:-81px -46px}
+div.kfm_panel_header a.kfm_panel_header_r{right:21px;background-position:-81px 0}
+div.kfm_panel_header a.kfm_panel_header_r:hover{right:21px;background-position:-81px -46px}
+div.kfm_panel_header a.kfm_panel_header__{right:41px;background-position:-61px 0}
+div.kfm_panel_header a.kfm_panel_header__:hover{right:41px;background-position:-61px -46px}
+div.kfm_panel_header a.kfm_panel_header_u{display:none}
+div.kfm_panel_header a.kfm_panel_header_d{display:none}
+div.kfm_panel_header a{float:right;text-decoration:none}
+#documents_loader{width:25px;float:left;margin:0;padding:3px;height:16px;}
+#folder_info{margin-left:40px}
+.kfm_empty{font-style:italic;color:#666}
+.kfm_file_icon{display:block;margin:5px;float:left;min-height:20px;background:url(icons/64x64/mimetypes/unknown.png) no-repeat top center;padding:64px 10px 5px 10px;text-align:center;color:#006A95;border:1px solid #fff;-moz-border-radius:10px;width:108px;overflow-x:hidden}
+.kfm_file_icon span.filename{text-decoration:underline}
+.kfm_file_icon.kfm_icontype_bz2{background-image:url(icons/64x64/mimetypes/bz2.png)}
+.kfm_file_icon.kfm_icontype_aac2{background-image:url(icons/64x64/mimetypes/aac2.png)}
+.kfm_file_icon.kfm_icontype_aac{background-image:url(icons/64x64/mimetypes/aac.png)}
+.kfm_file_icon.kfm_icontype_ape{background-image:url(icons/64x64/mimetypes/ape.png)}
+.kfm_file_icon.kfm_icontype_avi2{background-image:url(icons/64x64/mimetypes/avi2.png)}
+.kfm_file_icon.kfm_icontype_avi{background-image:url(icons/64x64/mimetypes/avi.png)}
+.kfm_file_icon.kfm_icontype_bz2{background-image:url(icons/64x64/mimetypes/bz2.png)}
+.kfm_file_icon.kfm_icontype_chm{background-image:url(icons/64x64/mimetypes/chm.png)}
+.kfm_file_icon.kfm_icontype_core{background-image:url(icons/64x64/mimetypes/core.png)}
+.kfm_file_icon.kfm_icontype_deb{background-image:url(icons/64x64/mimetypes/deb.png)}
+.kfm_file_icon.kfm_icontype_doc{background-image:url(icons/64x64/mimetypes/doc.png)}
+.kfm_file_icon.kfm_icontype_document{background-image:url(icons/64x64/mimetypes/document.png)}
+.kfm_file_icon.kfm_icontype_empty{background-image:url(icons/64x64/mimetypes/empty.png)}
+.kfm_file_icon.kfm_icontype_flac{background-image:url(icons/64x64/mimetypes/flac.png)}
+.kfm_file_icon.kfm_icontype_folder_setting{background-image:url(icons/64x64/mimetypes/folder_setting.png)}
+.kfm_file_icon.kfm_icontype_font{background-image:url(icons/64x64/mimetypes/font.png)}
+.kfm_file_icon.kfm_icontype_font_truetype{background-image:url(icons/64x64/mimetypes/font_truetype.png)}
+.kfm_file_icon.kfm_icontype_gz{background-image:url(icons/64x64/mimetypes/gz.png)}
+.kfm_file_icon.kfm_icontype_mov{background-image:url(icons/64x64/mimetypes/mov.png)}
+.kfm_file_icon.kfm_icontype_mp3{background-image:url(icons/64x64/mimetypes/mp3.png)}
+.kfm_file_icon.kfm_icontype_mp4{background-image:url(icons/64x64/mimetypes/mp4.png)}
+.kfm_file_icon.kfm_icontype_odt{background-image:url(icons/64x64/mimetypes/odt.png)}
+.kfm_file_icon.kfm_icontype_ogg{background-image:url(icons/64x64/mimetypes/ogg.png)}
+.kfm_file_icon.kfm_icontype_qt{background-image:url(icons/64x64/mimetypes/qt.png)}
+.kfm_file_icon.kfm_icontype_ram{background-image:url(icons/64x64/mimetypes/ram.png)}
+.kfm_file_icon.kfm_icontype_rar{background-image:url(icons/64x64/mimetypes/rar.png)}
+.kfm_file_icon.kfm_icontype_rm{background-image:url(icons/64x64/mimetypes/rm.png)}
+.kfm_file_icon.kfm_icontype_rmvb{background-image:url(icons/64x64/mimetypes/rmvb.png)}
+.kfm_file_icon.kfm_icontype_rpm{background-image:url(icons/64x64/mimetypes/rpm.png)}
+.kfm_file_icon.kfm_icontype_rtf{background-image:url(icons/64x64/mimetypes/rtf.png)}
+.kfm_file_icon.kfm_icontype_rt{background-image:url(icons/64x64/mimetypes/rt.png)}
+.kfm_file_icon.kfm_icontype_rv{background-image:url(icons/64x64/mimetypes/rv.png)}
+.kfm_file_icon.kfm_icontype_svg{background-image:url(icons/64x64/mimetypes/svg.png)}
+.kfm_file_icon.kfm_icontype_sxw{background-image:url(icons/64x64/mimetypes/sxw.png)}
+.kfm_file_icon.kfm_icontype_tar{background-image:url(icons/64x64/mimetypes/tar.png)}
+.kfm_file_icon.kfm_icontype_tgz{background-image:url(icons/64x64/mimetypes/tgz.png)}
+.kfm_file_icon.kfm_icontype_txt2{background-image:url(icons/64x64/mimetypes/txt2.png)}
+.kfm_file_icon.kfm_icontype_txt{background-image:url(icons/64x64/mimetypes/txt.png)}
+.kfm_file_icon.kfm_icontype_unknown{background-image:url(icons/64x64/mimetypes/unknown.png)}
+.kfm_file_icon.kfm_icontype_zip{background-image:url(icons/64x64/mimetypes/zip.png)}
+.kfm_file_icon.kfm_icontype_pdf{background-image:url(icons/64x64/mimetypes/pdf.png)}
+.kfm_file_icon.kfm_icontype_xls{background-image:url(icons/64x64/mimetypes/xls.png)}
+.kfm_file_icon.kfm_icontype_html{background-image:url(icons/64x64/mimetypes/html.png)}
+.kfm_file_icon.kfm_icontype_htm{background-image:url(icons/64x64/mimetypes/html.png)}
+.kfm_file_icon.kfm_icontype_php{background-image:url(icons/64x64/mimetypes/php.png)}
+.kfm_file_icon.kfm_icontype_rb{background-image:url(icons/64x64/mimetypes/ruby.png)}
+#kfm_files_listview_table .listview_headers th{background-image:url(tableicons/bg.gif);background-repeat:no-repeat;background-position:center right;background-color:#eee;border:solid #999;border-width:0 1px 1px 0;font-weight:bold;}
+#kfm_files_listview_table th.headerSortDown{background-image:url(tableicons/desc.gif)}
+#kfm_files_listview_table th.headerSortUp{background-image:url(tableicons/asc.gif)}
+#kfm_files_listview_table{border-spacing:0}
+#kfm_files_listview_table td{border:solid #ddd;border-width:0 1px 1px 0;padding:0}
+#kfm_files_listview_table .odd{background:#eee}
+#kfm_files_listview_table div.kfm_file_listview{padding:0 5px;border:0}
+#kfm_files_listview_table div.kfm_file_listview.selected.last_clicked{background-color:#99f;}
+#kfm_files_listview_table div.kfm_file_listview.selected{background-color:#66f;color:#fff}
+div:hover.kfm_file_icon{background-color:#f0f8ff;border-color:#bababa}
+div.kfm_file_icon.selected{background-color:#eee;border-color:#000}
+.last_clicked{border-style:dashed !important;border-color:red !important}
+.listview_icon{width:16px;height:16px;background:url(icons/16x16/mimetypes/unknown.png)}
+td.listview_icon_bz2{background-image:url(icons/16x16/mimetypes/bz2.png)}
+.listview_icon_bz2{background-image:url(icons/16x16/mimetypes/bz2.png)}
+.listview_icon_aac2{background-image:url(icons/16x16/mimetypes/aac2.png)}
+.listview_icon_aac{background-image:url(icons/16x16/mimetypes/aac.png)}
+.listview_icon_ape{background-image:url(icons/16x16/mimetypes/ape.png)}
+.listview_icon_avi2{background-image:url(icons/16x16/mimetypes/avi2.png)}
+.listview_icon_avi{background-image:url(icons/16x16/mimetypes/avi.png)}
+.listview_icon_bz2{background-image:url(icons/16x16/mimetypes/bz2.png)}
+.listview_icon_chm{background-image:url(icons/16x16/mimetypes/chm.png)}
+.listview_icon_core{background-image:url(icons/16x16/mimetypes/core.png)}
+.listview_icon_deb{background-image:url(icons/16x16/mimetypes/deb.png)}
+.listview_icon_doc{background-image:url(icons/16x16/mimetypes/doc.png)}
+.listview_icon_document{background-image:url(icons/16x16/mimetypes/document.png)}
+.listview_icon_empty{background-image:url(icons/16x16/mimetypes/empty.png)}
+.listview_icon_flac{background-image:url(icons/16x16/mimetypes/flac.png)}
+.listview_icon_folder_setting{background-image:url(icons/16x16/mimetypes/folder_setting.png)}
+.listview_icon_font{background-image:url(icons/16x16/mimetypes/font.png)}
+.listview_icon_font_truetype{background-image:url(icons/16x16/mimetypes/font_truetype.png)}
+.listview_icon_gz{background-image:url(icons/16x16/mimetypes/gz.png)}
+.listview_icon_mov{background-image:url(icons/16x16/mimetypes/mov.png)}
+.listview_icon_mp3{background-image:url(icons/16x16/mimetypes/mp3.png)}
+.listview_icon_mp4{background-image:url(icons/16x16/mimetypes/mp4.png)}
+.listview_icon_odt{background-image:url(icons/16x16/mimetypes/odt.png)}
+.listview_icon_ogg{background-image:url(icons/16x16/mimetypes/ogg.png)}
+.listview_icon_qt{background-image:url(icons/16x16/mimetypes/qt.png)}
+.listview_icon_ram{background-image:url(icons/16x16/mimetypes/ram.png)}
+.listview_icon_rar{background-image:url(icons/16x16/mimetypes/rar.png)}
+.listview_icon_rm{background-image:url(icons/16x16/mimetypes/rm.png)}
+.listview_icon_rmvb{background-image:url(icons/16x16/mimetypes/rmvb.png)}
+.listview_icon_rpm{background-image:url(icons/16x16/mimetypes/rpm.png)}
+.listview_icon_rtf{background-image:url(icons/16x16/mimetypes/rtf.png)}
+.listview_icon_rt{background-image:url(icons/16x16/mimetypes/rt.png)}
+.listview_icon_rv{background-image:url(icons/16x16/mimetypes/rv.png)}
+.listview_icon_svg{background-image:url(icons/16x16/mimetypes/svg.png)}
+.listview_icon_sxw{background-image:url(icons/16x16/mimetypes/sxw.png)}
+.listview_icon_tar{background-image:url(icons/16x16/mimetypes/tar.png)}
+.listview_icon_tgz{background-image:url(icons/16x16/mimetypes/tgz.png)}
+.listview_icon_txt2{background-image:url(icons/16x16/mimetypes/txt2.png)}
+.listview_icon_txt{background-image:url(icons/16x16/mimetypes/txt.png)}
+.listview_icon_unknown{background-image:url(icons/16x16/mimetypes/unknown.png)}
+.listview_icon_zip{background-image:url(icons/16x16/mimetypes/zip.png)}
+.listview_icon_pdf{background-image:url(icons/16x16/mimetypes/pdf.png)}
+.listview_icon_xls{background-image:url(icons/16x16/mimetypes/xls.png)}
+.listview_icon_html{background-image:url(icons/16x16/mimetypes/html.png)}
+.listview_icon_htm{background-image:url(icons/16x16/mimetypes/html.png)}
+.listview_icon_php{background-image:url(icons/16x16/mimetypes/php.png)}
+.listview_icon_rb{background-image:url(icons/16x16/mimetypes/ruby.png)}
+
+#kfm_directories,#kfm_directories table{border-spacing:0;margin:0;width:100%}
+#kfm_directories td{padding:0}
+#kfm_directories *{line-height:14px;}
+#kfm_directories .kfm_dir_lines_child{width:16px;height:18px;background:url(folders.gif) -16px 0 no-repeat}
+#kfm_directories .kfm_dir_lines_child a{font-size:0;text-indent:-4000px;display:block;width:16px;height:18px;background:url(folders.gif) -32px -18px}
+#kfm_directories .kfm_dir_lines_child a.kfm_dir_node_closed{background:url(folders.gif) -32px 0}
+#kfm_directories .kfm_dir_lines_lastchild{width:16px;height:18px;background:url(folders.gif) -16px -18px no-repeat}
+#kfm_directories .kfm_dir_lines_lastchild a{font-size:0;text-indent:-4000px;display:block;width:16px;height:18px;background:url(folders.gif) -32px -18px no-repeat}
+#kfm_directories .kfm_dir_lines_lastchild a.kfm_dir_node_closed{background:url(folders.gif) -32px 0px no-repeat}
+#kfm_directories .kfm_dir_lines_nochild{width:16px;background:url(folders.gif) 0 0 repeat-y}
+#kfm_directories .kfm_dir_name{background:url(folders.gif) no-repeat -48px 0;color:#006A95;text-decoration:underline;position:relative;padding-left:18px}
+#kfm_directories .kfm_dir_name div{background:#fff}
+#kfm_directories .kfm_dir_name.kfm_directory_open{background:url(folders.gif) -48px -18px no-repeat; background-color:#9cf}
+#kfm_directories .kfm_dir_name.kfm_directory_open div{background:#9cf}
+#kfm_directories .kfm_dir_name div:hover{color:#036}
+#message{top:2px; right:3px; position:absolute; z-index:10000; background-color: #f00; color: #000; font-weight:bold;}
+.button{margin-left:15px;color:#fff;background:#666;font-weight:bold;text-decoration:none;padding:2px 4px;display:block;text-align:center;border:2px solid;border-color:#ccc #999 #999 #ccc}
+.button:hover{color:#f00;background:#fff}
+
+/* IE-specific crap */
+.ie .kfm_panel_header{height:23px}
+
+#notice_wrapper{
+       width:120px
+}
+.notice{
+       display:block;
+       border:1px solid #000;
+       background:red;
+       color:#000;
+       padding:5px;
+       margin:5px
+}
+
+#kfm_lightboxWrapper{background:url(large_loader.gif) no-repeat center center}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/large_loader.gif b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/large_loader.gif
new file mode 100644 (file)
index 0000000..3596a61
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/large_loader.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/login.css b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/login.css
new file mode 100755 (executable)
index 0000000..8e55b0e
--- /dev/null
@@ -0,0 +1,7 @@
+th,td,input{font:12px sans-serif}
+body{margin:0;padding:0;text-align:center;background:#fff}
+form{padding:0;margin:200px auto 0;text-align:left;width:300px;border:1px solid #006;background:#f0f0f0}
+em{margin:0 auto;display:block}
+table{width:100%}
+th[colspan=2]{font-size:2em}
+td{vertical-align:top}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/prompt.css b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/prompt.css
new file mode 100644 (file)
index 0000000..46d6959
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+------------------------------
+       Impromptu's
+------------------------------
+*/
+.jqifade{
+       position: absolute;
+       background-color: #333333;
+}
+div.jqi{
+       position: absolute;
+       background-color: #d0dEb6;
+       padding: 10px; 
+       width: 300px;
+       text-align: left;
+}
+div.jqi .jqicontainer{
+       background-color: #e0eEc6;
+       padding: 5px; 
+       color: #ffffff;
+       font-weight: bold;
+}
+div.jqi .jqimessage{
+       background-color: #c0cEa6;
+       padding: 10px;
+}
+div.jqi .jqibuttons{
+       text-align: center;
+       padding: 5px 0 0 0;
+}
+div.jqi button{
+       padding: 3px 10px 3px 10px;
+       margin: 0 10px;
+}
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/small_loader.gif b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/small_loader.gif
new file mode 100644 (file)
index 0000000..34852a1
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/small_loader.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/tableicons/asc.gif b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/tableicons/asc.gif
new file mode 100644 (file)
index 0000000..7415786
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/tableicons/asc.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/tableicons/bg.gif b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/tableicons/bg.gif
new file mode 100644 (file)
index 0000000..fac668f
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/tableicons/bg.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/tableicons/desc.gif b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/tableicons/desc.gif
new file mode 100644 (file)
index 0000000..3b30b3c
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/themes/default/tableicons/desc.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/upload.php b/ipf/admin/media/tiny_mce/plugins/kfm/upload.php
new file mode 100644 (file)
index 0000000..73abbf6
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+/**
+ * KFM - Kae's File Manager
+ *
+ * upload.php - uploads a file and adds it to the db
+ *
+ * @category None
+ * @package  None
+ * @author   Kae Verens <kae@verens.com>
+ * @author   Benjamin ter Kuile <bterkuile@gmail.com>
+ * @license  docs/license.txt for licensing
+ * @link     http://kfm.verens.com/
+ */
+require_once 'initialise.php';
+$errors = array();
+if ($kfm_allow_file_upload) {
+    $file     = isset($_FILES['kfm_file'])?$_FILES['kfm_file']:$_FILES['Filedata'];
+    $filename = $file['name'];
+    $tmpname  = $file['tmp_name'];
+    $cwd      = $kfm_session->get('cwd_id');
+    if(!$cwd) $errors[] = kfm_lang('CWD not set');
+    else {
+        $toDir = kfmDirectory::getInstance($cwd);
+        $to = $toDir->path.'/'.$filename;
+        if (!is_file($tmpname)) $errors[] = 'No file uploaded';
+        else if (!kfmFile::checkName($filename)) {
+            $errors[] = 'The filename: '.$filename.' is not allowed';
+        }
+    }
+               if ($cwd==1 && !$kfm_allow_files_in_root) $errors[] = 'Cannot upload files to the root directory';
+    if (file_exists($to)) $errors[] = 'File already exists'; // TODO new string
+    if (!count($errors)) {
+        move_uploaded_file($tmpname, $to);
+        if (!file_exists($to)) $errors[] = kfm_lang('failedToSaveTmpFile', $tmpname, $to);
+        else if ($kfm_only_allow_image_upload && !getimagesize($to)) {
+            $errors[] = 'only images may be uploaded';
+            unlink($to);
+        } else {
+            chmod($to, octdec('0'.$kfm_default_upload_permission));
+            $fid  = kfmFile::addToDb($filename, $kfm_session->get('cwd_id'));
+            $file = kfmFile::getInstance($fid);
+            if (function_exists('exif_imagetype')) {
+                $imgtype = @exif_imagetype($to);
+                if ($imgtype) {
+                    $file    = kfmImage::getInstance($file);
+                    $comment = '';
+                    if ($imgtype==1) { // gif
+                        $fc    = file_get_contents($to);
+                        $arr   = explode('!', $fc);
+                        $found = 0;
+                        for ($i = 0;$i<count($arr)&&!$found;++$i) {
+                            $block = $arr[$i];
+                            if (substr($block, 0, 2)==chr(254).chr(21)) {
+                                $found   = 1;
+                                $comment = substr($block, 2, strpos($block, 0)-1);
+                            }
+                        }
+                    } else {
+                        $data = @exif_read_data($to, 0, true);
+                        if (is_array($data)&&isset($data['COMMENT'])&&is_array($data['COMMENT'])) $comment = join("\n", $data['COMMENT']);
+                    }
+                    $file->setCaption($comment);
+                } else if (isset($_POST['kfm_unzipWhenUploaded'])&&$_POST['kfm_unzipWhenUploaded']) {
+                    kfm_extractZippedFile($fid);
+                    $file->delete();
+                }
+            }
+        }
+    }
+} else $errors[] = kfm_lang('permissionDeniedUpload');
+if (isset($_REQUEST['swf']) && $_REQUEST['swf']==1) {
+    if(count($errors))echo join("\n", $errors);
+    else echo 'OK';
+    exit;
+}
+?>
+<html>
+    <head>
+        <script type="text/javascript">
+<?php
+$js = isset($_REQUEST['js'])?$js:'';
+if (isset($_REQUEST['onload'])) echo $_REQUEST['onload'];
+else if (isset($_REQUEST['onupload'])) echo $_REQUEST['onupload'];
+else if (count($errors)) echo 'alert("'.addslashes(join("\n", $errors)).'");';
+else echo 'parent.kfm_vars.startup_selectedFiles=['.$fid.'];parent.x_kfm_loadFiles('.$kfm_session->get('cwd_id').',parent.kfm_refreshFiles);parent.kfm_dir_openNode('.$kfm_session->get('cwd_id').');'.$js;
+?>
+        </script>
+    </head>
+    <body>
+    </body>
+</html>
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_add.png b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_add.png
new file mode 100644 (file)
index 0000000..5fc85f9
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_add.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_add_blt.png b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_add_blt.png
new file mode 100644 (file)
index 0000000..847ab1f
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_add_blt.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_empty.png b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_empty.png
new file mode 100644 (file)
index 0000000..73547e4
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_empty.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_empty_blt.png b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_empty_blt.png
new file mode 100644 (file)
index 0000000..df9babb
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_empty_blt.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_full.png b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_full.png
new file mode 100644 (file)
index 0000000..7607a97
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_full.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_full_blt.png b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_full_blt.png
new file mode 100644 (file)
index 0000000..d5e27d9
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/clipboard_full_blt.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/widget.js b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/clipboard/widget.js
new file mode 100644 (file)
index 0000000..a0da64c
--- /dev/null
@@ -0,0 +1,121 @@
+function Clipboard(){
+       this.istarget=0;
+       this.name='Clipboard'; // TODO: new string
+       this.files=[];
+       this.folders=[];
+       this.display=function(){
+               el=new Element('div',{
+                       'id':'kfm_widget_clipboard_container',
+                       'class':'widget_clipboard',
+                       'title':this.name,
+                       'styles':{
+                               'float':'left',
+                               'padding':'5px',
+                               'width':'70px',
+                               'height':'70px',
+                               'background-image':'url(\'widgets/clipboard/clipboard_empty.png\')',
+                               'background-repeat':'no-repeat',
+                               'font-size':'10px'
+                       },
+                       'events':{
+                               'mouseover':function(){
+                                       if($j('#kdnd_drag_wrapper').length){
+                                               if(kfm_theme=='blt') this.style.backgroundImage='url(\'widgets/clipboard/clipboard_add_blt.png\')';
+                                               else this.style.backgroundImage='url(\'widgets/clipboard/clipboard_add.png\')';
+                                       }
+                               },
+                               'mouseout':function(){this.setAppearance();},
+                               'click':function(){
+                                       if(selectedFiles.length){
+                                               this.action(selectedFiles,[]);
+                                               kfm_selectNone();
+                                       }
+                               }
+                       }
+               });
+               if(kfm_theme=='blt'){
+                       el.empty_url='widgets/clipboard/clipboard_empty_blt.png';
+                       el.full_url='widgets/clipboard/clipboard_full_blt.png';
+                       $j(el).css('background-image','url('+el.empty_url+')');
+               }else{
+                       el.empty_url='widgets/clipboard/clipboard_empty.png';
+                       el.full_url='widgets/clipboard/clipboard_full.png';
+               }
+               el.files=[];
+               el.folders=[];
+               el.setAppearance=function(){
+                       var html='';
+                       if(this.files.length || this.folders.length){
+                               this.style.backgroundImage='url(\''+this.full_url+'\')';
+                               if(this.files.length)html+=this.files.length+' file'; // TODO: new string
+                               if(this.files.length>1)html+='s';
+                               if(this.folders.length)html+='<br/>'+this.folders.length+' folders'; // TODO: new string
+                       }
+                       else this.style.backgroundImage='url(\''+this.empty_url+'\')';
+                       this.innerHTML=html;
+               }
+               el.action=function(files,folders){
+                       for(var i=0;i<files.length;i++){
+                               if(!this.files.contains(files[i]))this.files.push(files[i]);
+                       }
+                       for(var i=0;i<folders.length;i++){
+                               if(!this.folders.contains(folders[i]))this.folders.push(folders[i]);
+                       }
+                       this.setAppearance();
+               };
+               el.clearContents=function(){
+                       this.files=[];
+                       this.folders=[];
+                       this.setAppearance();
+               };
+               el.pasteContents=function(){
+                       if(this.files.length)x_kfm_copyFiles(this.files,kfm_cwd_id,function(m){
+                               kfm_showMessage(m);
+                               x_kfm_loadFiles(kfm_cwd_id,kfm_refreshFiles);
+                       });
+                       if(this.folders.length)kfm.alert('paste of folders is not complete'); //TODO: complete
+                       this.clearContents();
+               };
+               kfm_addContextMenu(el,function(e){
+                       e=new Event(e);
+                       var el=$('kfm_widget_clipboard_container');
+                       var links=[];
+                       var plugins=kfm_getLinks(el.files);
+                       { // add the links
+                               plugins.push(['$("kfm_widget_clipboard_container").clearContents()','clear clipboard']); // TODO: new string
+                               plugins.push(['$("kfm_widget_clipboard_container").pasteContents()','paste clipboard contents']); // TODO: new string
+                       }
+                       kfm_createContextMenu(e.page,plugins);
+               });
+               setTimeout("kdnd_makeDraggable('widget_clipboard');",1);
+               return el;
+       }
+       return this;
+}
+kfm_addWidget(new Clipboard());
+kdnd_addDropHandler('widget_clipboard','#kfm_right_column',function(e){
+       e.sourceElement.pasteContents();
+});
+kdnd_addDropHandler('kfm_file','.widget_clipboard',function(e){
+       if(!selectedFiles.length)kfm_addToSelection(e.sourceElement.id.replace(/.*_/,''));
+       e.targetElement.action(selectedFiles,[]);
+});
+kdnd_addDropHandler('kfm_dir_name','.widget_clipboard',function(e){
+       var dir_from=parseInt($E('.kfm_directory_link',e.sourceElement).node_id);
+       e.targetElement.action([],[dir_from]);
+});
+kdnd_addDropHandler('widget_clipboard','.kfm_dir_name',function(e){
+       if(!e.sourceElement.files.length)return;
+               //dir_over=e.targetElement.node_id;
+       var dir_over=parseInt($E('.kfm_directory_link',e.targetElement).node_id);
+               var links=[];
+               links.push(['x_kfm_copyFiles(['+e.sourceElement.files.join(',')+'],'+dir_over+',kfm_showMessage);kfm_selectNone()','copy files']);
+               links.push(['x_kfm_moveFiles(['+e.sourceElement.files.join(',')+'],'+dir_over+',function(e){if($type(e)=="string")return alert("error: could not move file[s]");kfm_removeFilesFromView(['+selectedFiles.join(',')+'])});kfm_selectNone()','move files',0,!kfm_vars.permissions.file.mv]); // TODO: new string
+               kfm_createContextMenu(e.page,links);
+       e.sourceElement.clearContents();
+});
+kdnd_addDropHandler('widget_clipboard','.widget_trash',function(e){
+       if(!e.sourceElement.files.length)return;
+       e.targetElement.action(e.sourceElement.files);
+       e.sourceElement.clearContents();
+});
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/widgets/trash/trash.png b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/trash/trash.png
new file mode 100644 (file)
index 0000000..ba61405
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/trash/trash.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/widgets/trash/trash_blt.png b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/trash/trash_blt.png
new file mode 100644 (file)
index 0000000..b37e9c8
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/trash/trash_blt.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/kfm/widgets/trash/widget.js b/ipf/admin/media/tiny_mce/plugins/kfm/widgets/trash/widget.js
new file mode 100644 (file)
index 0000000..bbcccad
--- /dev/null
@@ -0,0 +1,34 @@
+function Trash(){
+       this.istarget=0;
+       this.name='Trash';
+       this.display=function(){
+               if(!kfm_vars.permissions.file.rm)return false;
+               el=new Element('img',{
+                       'src':'widgets/trash/trash.png',
+                       'class':'widget_trash',
+                       'title':this.name,
+                       'styles':{
+                               'display':'block',
+                               'float':'left',
+                               'width':'70px',
+                               'height':'70px'
+                       }
+               });
+               if(kfm_theme=="blt")$j(el).attr('src','widgets/trash/trash_blt.png');
+               el.action=function(files,dirs){
+                       kfm_deleteFiles(files);
+               }
+               return el;
+       }
+       this.action=function(files){
+       }
+}
+if(kfm_vars.permissions.file.rm)kfm_addWidget(new Trash());
+kdnd_addDropHandler('kfm_file','.widget_trash',function(e){
+       if(!selectedFiles.length)kfm_addToSelection(e.sourceElement.id.replace(/.*_/,''));
+       e.targetElement.action(selectedFiles,[]);
+});
+kdnd_addDropHandler('kfm_dir_name','.widget_trash',function(e){
+       var dir_from=parseInt($E('.kfm_directory_link',e.sourceElement).node_id);
+       e.targetElement.action([],[dir_from]);
+});
index a3e27023ccfc0e1ebb18c5141b01b1f4d972e6ab..962cb76e40f9e354fc9bf3a93e0ac7402ab269fa 100644 (file)
@@ -51,9 +51,19 @@ class IPF_Form_Widget_HTMLInput extends IPF_Form_Widget
             IPF_Form_Widget_HTMLInput::$js_include = true;
                     $out .= '<script language="javascript" type="text/javascript" src="'.IPF::get('tiny_mce_url').'tiny_mce.js"></script>'."\n";
                     $out .='<script language="javascript" type="text/javascript">
+                                       function kfm_for_tiny_mce(field_name, url, type, win){
+                                         window.SetUrl=function(url,width,height,caption){
+                                          win.document.forms[0].elements[field_name].value = url;
+                                          if(caption){
+                                           win.document.forms[0].elements["alt"].value=caption;
+                                           win.document.forms[0].elements["title"].value=caption;
+                                          }
+                                         }
+                                         window.open("/media/tiny_mce/plugins/kfm/index.php?mode=selector&lang=en&type="+type,"kfm","modal,width=800,height=600");
+                                       }
                tinyMCE.init({
                     theme_advanced_buttons1 : "bold, italic, separator, undo, redo, separator, bullist, numlist, outdent, indent, separator, justifyleft, justifycenter, justifyright, separator, link, unlink, forecolor, backcolor, sub, sup, separator, preview",
-                    theme_advanced_buttons2 : "code, fullscreen, images, charmap, separator, pastetext, pasteword, selectall, removeformat, separator, formatselect, fontselect, fontsizeselect",
+                    theme_advanced_buttons2 : "code, fullscreen, image, link, charmap, separator, pastetext, pasteword, selectall, removeformat, separator, formatselect, fontselect, fontsizeselect",
                     theme_advanced_buttons3 : "",
                     theme_advanced_toolbar_location : "top",
                     theme_advanced_toolbar_align: "left",
@@ -61,7 +71,7 @@ class IPF_Form_Widget_HTMLInput extends IPF_Form_Widget
                     editor_selector : "htmlEditor",
                        theme : "advanced",
                        convert_urls:"false",
-                       plugins : "inlinepopups, images, charmap, paste, table, fullscreen, preview, print",
+                       plugins : "inlinepopups, charmap, paste, table, fullscreen, preview, print, advlink, advimage",
                     button_tile_map : true,
                     fix_list_elements : true,
                     gecko_spellcheck : true,
@@ -71,7 +81,8 @@ class IPF_Form_Widget_HTMLInput extends IPF_Form_Widget
                     height : "350",
                     relative_urls : false,
                     remove_script_host : true,
-                    content_css : "/media/tiny_mce/themes/advanced/skins/default/content.css"
+                    content_css : "/media/tiny_mce/themes/advanced/skins/default/content.css",
+                    file_browser_callback : "kfm_for_tiny_mce"
                });
             </script>';
         }